Tutorial Kotlin para ProgramadoresDescripción completa
Manhole Construction BS Standard
Esta edición destaca la protección visual y contiene información técnica sobre ropa de protección química, clasificación de materiales peligrosos, y medidas de bioseguridad, efectos adversos…Descripción completa
FREEFull description
Livro sobre computação gráfica.Descrição completa
Examen 1 1000 programadores Corfo - Chile
listagem de livros para aprendizagem de programaçãoDescrição completa
S D O I I T U A L R G C
8ª ENTREGA DEL COLECCIONABLE
N I D C
AÑO O XI. XI. 2. 2.ªª ÉPOC ÉPOCA A • Nº 124 • Precio: 6 € (Españ (España) a) (IVA inclu incluido) ido) • AÑ
UNA PUBLICACIÓN DE:
ROFESI ESIONA ONALES LES S. L . REVISTAS PROF
Y ADEMÁS… ACTUALID ACTUA LIDAD AD 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 Acce so a orí oríge genes nes de dato datos s 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 00124
Noticias, javaHispano y Opinión, Libros, Preguntas y Respuestas
8
413042 303299
EDITORIAL Otra “sopa de letras” Número 124 - Mayo Mayo 2005 Edita: REVISTAS PROFESIONALES S.L. [email protected] C/ Valentin Beato 42, 3ª. 28037 - Madrid. http://www.revistasprofesionales.com http://digital.revistasprofesionales.com Editor Agustín Buelta •••••••••••••••••••••••••••••••••• Coordinación Técnica-Redac Técnica-Redacción ción Carlos Laparra •••••••••••••••••••••••••••••••••• Maquetación Raúl Clavijo •••••••••••••••••••••••••••••••••• Asesoría de Publicidad Felipe Ribagorda Tel.: 91 304 87 64 Barcelona C/ Rocafort, 241/243, 5º 1ª Mariano Sánchez Tel.: 93 322 12 38 •••••••••••••••••••••••••••••••••• Suscripciones
Nuevamente, 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 se avecina. Como el lector podrá comprobar en la entrevista publicada en este número de Sólo Programadores , los nuevos estándares sobre los que “correrán” los próximos servicios 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 embargo tanto SIP como Parlay parece que ya se han hecho un hueco entre los puestos más importantes. De hecho, hablamos aquí de estándares “nuevos” y “emergentes” pero esto no es cierto al 100%. SIP, por ejemplo, es un protocolo cuyo objetivo es permitir el tratamiento de los servicios de voz como una aplicación más de la red, y el primer borrador de este protocolo surgió en febrero de 1996 (SIPv1), sin embargo en el mes de diciembre de ese mismo año se publicó la segunda versión (SIPv2). En febrero de 1999 SIP se convirtió ya en un estándar, publicado como RFC 2543, aunque en junio de 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, parece que es ahora cuando las empresas proveedoras de infraestructuras software como BEA Systems están empezando a darles soporte, para conseguir de una vez por todas la tan ansiada integración de voz en las redes de datos.
Tel: 91 304 87 64 Fax: 91 327 13 03
••••••••••••••••••••••••••••••••••• Impresión Ideas de Impresión ••••••••••••••••••••••••••••••••••• Distribución Motorpress Ibérica
SUMARIO
ACTUALIDAD 12 BEA
entra en la red con Da Vinci 16 Sun Certified Enterprise Architect for J2EE Distribución Mexico DIMSA - Angel Bosch Bosch [email protected] Distribución, números atrasados y suscripciones Renacimiento, 180. Col. San Juan Tlihuaca Azcapotzalco. 02400 México D.F. Distribución Argentina Capital Federal: Distrimachisa Interior: York Agency, 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 sus colaboradores en los artículos firmados. El editor prohibe expresamente la reproducción total o parcial de los contenidos de la revista sin su autorización escrita.
Depósito legal: M-26827-1994 PRINTED IN SPAIN COPYRIGHT 30-04-20 30-04-2005 05 P.V.P. 6,00 Euros Precio en Canarias, Ceuta y Melilla: 6,15 Euros
Asociación Española de Editoriales de Publicaciones Periódicas
DISPOSITIVOS MÓVILES 20 Juegos
de calidad comercial en J2ME (III)
MIDDLEWARE 28 Programac Programación ión 36 XAML
distribuida en .NET (II)
(IV)
REDES 42 Sistemas
de mensajería con Java Message Service (I)
DISEÑO 50 Together
Architect, el enlace entre el problema y la solución multiplataforma para aplicacion aplicaciones es C++ (y III) 54 Diseño multiplataforma Y ad ademá emá s… 04 Noticias 08 javaHispano: javaHispano: jH.com,
joda-time,, columna de opinión y más joda-time 10 Canal Panda: Panda: Pharming, nueva nueva técnica de fraude fraude 60 Preguntas y respuestas con PHP 64 Libros: Desarrollo web con 66 Contenido del CD-ROM
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 conseguir el éxito de sus partners ISVs (fabricantes independientes de software) y ayudarles a mejorar la satisfacción de sus clientes. Se trata de un servicio de consultoría telefónica diseñado para ayudarles en la creación y desarrollo de nuevos programas a partir de las tecnologías de la compañía. Con esta consultoría especializada Microsoft mejora notablemente el servicio habitual que se proporciona en concepto de mantenimiento de software con una ayuda pro-activa gestionada por un técnico experto en desarrollo de aplicaciones y nuevos programas, migración de productos y gestión de códigos.
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, ha anunciado dos nuevos productos: Crystal Reports XI y Crystal Reports Server XI, ambos orientados a dar solución a la generación de informes.
Crystal Reports XI Los desarrolladores y otros profesionales informáticos necesitan poder acceder rápidamente a los datos, integrar con facilidad la funcionalidad de reporting dentro de sus aplicaciones empresariales, y gestionar el formateo y distribución de información a través de la web. Para atender esta demanda, Crystal Reports XI ofrece nuevas funciones, como por ejemplo mejores controladores de conectividad para acceder con facilidad a cualquier fuente de datos, creación de plantillas para personalizar informes, herramientas de diseño intuitivas, un banco de trabajo 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 abierto que centra su actividad en la oferta de una plataforma de desarrollo universal, anuncian que BEA se ha integrado en Eclipse como miembro del Consejo 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 liderazgo del proyecto WTP (Web Tools Platform). Además, BEA va a proponer un nuevo proyecto sobre el Lenguaje de Herramientas de Desarrollo y también va a fusionar su proyecto de código abierto AspectWerkz con el proyecto AspectJ de Eclipse, como ya adelantó el mes pasado Sólo Programadores en la sección de la comunidad javaHispano.
SOLO PROGRAMADORES nº 124
4
Este nuevo beneficio forma parte del Partner Program y permite a los ISVs seleccionar aquellos servicios que se ajustan a sus necesidades dentro de una amplia oferta de asesoramiento. En función del nivel alcanzado por el partner dentro del programa, Microsoft ofrece distintas horas de asesoramiento: 10 a los partners suscritos al programa Empower, 15 a los Certified y 20 a los Gold Certified. Los partners que quieran ampliar información sobre este nuevo servicio pueden visitar la web http://www.microsoft.com http://www.microsoft.com/spain/partner/isv/default.asp. /spain/partner/isv/default.asp. Para Susana Núñez, responsable del Programa de Partners en Microsoft Iberica, “este nuevo servicio es un importante valor añadido del que pueden beneficiarse todos los ISVs. Forma parte del compromiso de permanente colaboración que tenemos con todos nuestros partners y nos permite mejorar y avanzar juntos en el desarrollo de tecnologías que ayuden a mejorar la productividad de las empresas.”
virutal sobre el que organizar y decidir la manera de programar la generación de los informes, etc.
Crystal Reports Server XI, Crystal Reports Server XI es una versión orientada a las pequeñas y medianas empresas, ya que supone una solución de generación de informes empaquetada que incluye todo lo que las organizaciones de mediano tamaño pueden necesitar para crear, distribuir y gestionar informes a través de la web, integrando las funciones de reporting dentro de sus aplicaciones ofimáticas. Crystal Reports Server XI pone a disposición de las organizaciones las mismas funcionalidades de generación de informes que las que poseen las grandes empresas, pero sin el coste ni la comple jidad de esas implanta implantaciones. ciones. Además Además,, cuenta con un año de mantenimiento y asistencia técnica. Actualmente la Fundación Eclipse cuenta con 91 miembros, pero sólo ocho de estas compañías figuran como desarrolladores estratégicos. BEA ha sido también elegida para liderar el proyecto WTP (Web Tools Platform), que desarrolla herramientas de infraestructura para soportar J2EE y desarrollo de aplicaciones Web. BEA planea incorporar capacidades WTP dentro de futuros lanzamientos de BEA WebLogic Workshop. Además de demostrar su compromiso con la Fundación Eclipse desde el punto de vista corporativo, BEA también tiene previsto anunciar futuros desarrollos que vendrán a reforzar el compromiso desde el punto de vista tecnológico. Bajo la denominación de código “Daybreak,” BEA va a diseñar la próxima versión de BEA WebLogic Workshop, el entorno de desarrollo integrado de la compañía, que soportará el framework de Eclipse. Daybreak ofrecerá un amplio entorno de desarrollo que comprende características de Workshop de fácil uso, así como un framework de alta productividad para el desarrollo de arquitecturas orientadas a servicios, además de frameworks de Eclipse y un abanico de plug-ins, también de Eclipse.
http://digital.revistasprofesionales.com
NOTICIAS
BORLAND
Borland presta un mayor soporte a Eclipse Borland ha ampliado significativamente su soporte a Eclipse, comunidad de código abierto, a la vez que plataforma de desarrollo universal que soporta múltiples lenguajes y tecnologías. Borland se ha incorporado como desarrollador estratégico a la Junta Directiva de la Fundación Eclipse desde donde desempeñará un papel importante en el progreso de esta tecnología, mediante la aportación de un equipo de desarrollo para ampliar la plataforma Eclipse. Borland fomentará el uso de Eclipse como plataforma a lo largo de toda su línea de productos de gestión del ciclo de vida de las aplicaciones (ALM). De este modo, junto con el creciente soporte de Borland a Microsoft Visual Studio, la compañía continuará ofreciendo a los clientes la posibilidad de elegir la tecnología para sus soluciones ALM corporativas, mientras contribuye a reducir la creciente complejidad de los entornos de TI heterogéneos. Eclipse y Visual Studio se han convertido en dos de las plataformas de desarrollo líderes en la actualidad y Borland ayudará a sus clientes a estrechar
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 continua y gratuita, dirigido a sus partners, que tendrán lugar cada martes hasta el próximo mes de junio. El plan de formación se imparte a través de Webinars, seminarios online que tienen como objetivo cualificar a los mejores partners de BEA e incrementar el número de expertos en las soluciones de BEA, utili-
MICROSOFT
Microsoft y Telefónica Móviles firman un acuerdo dirigido a ofrecer apoyo a los desarrolladores de software Mauricio Ulargui, director de la División de Desarrolladores de Plataforma de Microsoft Ibérica y José María Soler, director de Aplicaciones y MovilForum de Telefónica Móviles España, han firmado un acuerdo de colaboración por el que ambas compañías se comprometen a poner en marcha una serie de actividades dirigidas a ofrecer su apoyo a la comunidad técnica de desarrolladores de software. La importancia que este colectivo ha adquirido en el campo de las nuevas tecnologías ha llevado a Microsoft y Telefónica Móviles España a crear programas específicos orientados a los desarrolladores. MSDN (Microsoft Developer Network) se fundó a principios de 1992 y desde entonces se ha convertido en el principal vehículo de comunicación que mantiene la compañía con esta comunidad. Por su parte, con una antigüedad de más de cuatro años, MovilForum es el foro
SOLO PROGRAMADORES nº 124
6
la distancia entre ambas con el fin de que puedan aprovechar mejor las inversiones que ya han realizado. En este sentido, y para impulsar los avances ALM de la plataforma Eclipse, Borland liderará la propuesta para un nuevo marco de modelado gráfico que se sumará a la tecnología de modelado actual en la comunidad Eclipse. Y es que no hay que olvidar que el modelado comienza a cobrar más protagonismo entre las empresas, como vía para reducir la complejidad de TI, mejorar la eficiencia y colaboración de los equipos y acercar los requisitos de TI y de negocio. Como fiel defensor de los sistemas abiertos, de las plataformas independientes y de la libre elección del cliente, Borland continuará soportando productos y servicios, tanto en Eclipse, como en el marco de trabajo Microsoft Visual Studio, mientras también avanza las características y funcionalidades de su IDE Java JBuilder. zadas actualmente actualmente por más de 15.000 15.000 empresas de todo el mundo. mundo. Los partners de BEA que quieran participar en los webinars podrán elegir entre más de 15 cursos diferentes que analizan contenidos como la creación de portales, desarrollos en J2EE, integración de aplicaciones empresariales o estándares de servicios web, entre otras temáticas. También se ofrece información a los partners sobre las últimas soluciones que BEA lance al mercado, como la nueva versión de su servidor de aplicaciones BEA WebLogic 9.0 o acerca de su proyecto de código abierto Apache Beehive. Los partners de BEA que quieran participar en su programa de formación pueden consultar la agenda en la URL http://es.bea.com/eventos/webinars/index.jsp o dirigirse por teléfono al departamento de marketing de BEA Systems (91 384 65 34). que Telefónica Móviles pone a disposición de sus partners para proporcionarles la ayuda y los conocimientos necesarios con el fin de fomentar el desarrollo de aplicaciones móviles sobre la red MoviStar. El acuerdo alcanzado por Microsoft y Telefóni Telefónica ca Móviles España incluye una serie de acciones de colaboración mutua, entre las que cabría destacar la participación de la operadora en DevDay, el principal evento que anualmente celebra Microsoft con los desarrolladores de software, el patrocinio de Microsoft en la Feria MovilForum, dando a conocer la aplicación de su tecnología en el área de la movilidad, la colaboración de Telefónica Móviles en las sesiones sobre Smart Client de los eventos MSDN Workshop que se celebren en Madrid y Barcelona, y la incorporación de los elementos de movilidad real propios de Telefónica MoviStar en ISV Walqa Lab, el principal laboratorio tecnológico de Microsoft a disposición de los ISVs españoles. Mauricio Ulargui, director de la División de Desarrolladores de Plataforma de Microsoft Ibérica (izquierda) y José María Soler, director de Aplicaciones y MovilForum de Telefónica Móviles España (derecha), durante la firma del acuerdo de colaboración.
http://digital.revistasprofesionales.com
JAVAHISP JAVAHI SPANO ANO
Actual Actu alid idad ad Ja Java va de la mano de javaHispano javaHispano lanza un nuevo portal dedicado a empresas: javaHispano.com Hasta el presente javaHispano mantenía dos portales, uno dedicado a informar sobre las últimas novedades, dar apoyo, formar y, en general, servir de cauce para compartir conocimiento entre los desarrolladores Java (javaHispano.org); y otro orientado a dar soporte y fomentar el desarrollo de soluciones libres en torno a las tecnologías Java (javaHispano.net). En javaHispano estamos convencidos de que las empresas pueden realizar inestimables contribuciones a la plataforma Java en general, y a los desarrolladores y al Software Libre en 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, tengan 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 los servicios y productos que ofrecen. Para aquellas que lo deseen, javaHispano.com también les permitirá colaborar activamente para incrementar el valor del portal mediante la publicación de casos de éxito, informes, noticias y comparativas, así como con cualquier otra iniciativa 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 y por su localización geográfica; así como búsquedas entre los productos ofertados por las empresas por categoría, tecnología y licencia. En acorde 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 completamente gratuito, si bien, dados los gastos de mantenimiento del portal, javaHispano aceptará donativos de las empresas registradas.
Librería alternativa para el procesado de fechas Una de las clases Java que menos simpatías crea entre los desarrolladores es, sin duda, “java.util.Date”. Sus métodos son poco intuitivos, a menudo no existe un método que nos proporcione la funcionalidad que necesitamos y, en la actualidad, la mayor parte de ellos se encuentran "deprecated". A esto se añade el hecho de que las fechas no son inmutables, para muchos una mala decisión de diseño. Joda-time (http://joda-time.sourceforge.net) (http://joda-time.sourceforge.net) es una librería Open Source con licencia Apache 2.0 para el 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 localidad. Aunque hace bastante tiempo que el proyecto es funcional recientemente han liberado la versión 1.0. Junto a estas líneas podéis observar un pequeño código de ejemplo, y en el CD-ROM se incluye 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();
SOLO PROGRAMADORES nº 124
8
http://digital.revistasprofesionales.com
JAVAHISP JAVAHI SPANO ANO
javaHispano
JBenchmark3D: mide la potencia gráfica de tu móvil
OPINIÓN
XML: uso y abuso
JBenchmark (http://www.jbenchmark.com) es una aplicación Java para dispositivos móviles que permite medir su rendimiento ejecutando una serie de tests sobre él. Hasta hace poco 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 estas líneas, orientado a medir el rendimiento gráfico de los terminales móviles. JBenchmark3D mide la potencia gráfica del dispositivo realizando tests relacionados con el manejo de triángulos, texturas, escenas de bajas calidad para juegos basados en motores 3D, y escenas de alta calidad para dispositivos con aceleración 3D por hardware. Al igual que sus hermanos, JBenchmark3D se descarga gratuitamente, y los resultados se pueden enviar a la web para ser considerados en las estadísticas que, de prácticamente todos los terminales móviles del mercado, se muestran en el portal de JBenchmark.
El XML es un estupendo formato para estructuestru cturar información jerárquica o en árbol en texto plano, gracias a esta cualidad y a ser una “lengua franca” independiente de las plataformas, se está usando casi para todo: representación visual (XHTML), descriptor de contenidos (RDF), comunicación de datos y acciones (SOAP), configuración y almacenamiento de datos a medida, descriptor de tareas en desarrollo (Ant), generación de código (JAXB), descriptor “ortogonal” entre el lenguaje de programación y mundos paralelos: HTML y código en los frameworks web, descriptores de tablas/clases en EJBs, vínculos con aspectos en AspectWerkz, serialización en XStream etc, por citar ejemplos Java. Parece que tendremos XML para rato.
IntelliJ IDEA gratis para desarrolladore desarrolladoress de sofware libre
Jetbrains, compañía desarrolladora de uno de los principales IDE Java, IntelliJ IDEA, ha anunciado que apoyará al movimiento del Sofware Libre regalando licencias de su IDE a los desarrolladores que participen en proyectos libres. Las condiciones para acceder a estas licencias son participar en un proyecto que: se distribuya bajo una licencia aprobada por la OSI, tenga una web propia y cuente con una comunidad activa. Las peticiones pueden realizarse desde http://www.jetbrains.com/idea/opensource/application.htm.
Sin embargo existe la fuerte tendencia de usar XML como “metalenguaje de programación secuencial”, con ejemplos relevantes como Ant (con gran éxito), algunos frameworks web y el “modelado y coreografía de procesos de negocio” en WebServices (BPML, BPEL, CDL etc.). La sintaxis en ocasiones puede llegar a ser tan compleja que son necesarias herramientas, y adolecen de un gran problema: pobre expresividad. XML presenta grandes dificultades para “expresar” comportamiento que fácilmente puede expresarse en un lenguaje normal con un buena API, de hecho, más reutilizable y extensible. Teniendo en cuenta la enorme influencia sintáctica que ha tenido el C/C++ en los lenguajes modernos no sería difícil inventar una nueva lengua franca multiplataforma teórica, la OMG lo hizo con el IDL para declaraciones, el W3C lo usa con éxito para el DOM, ¿Por qué no añadir también comportamiento? ¿Un Behavior Definition Language? Más clases, interfaces y herencia y quizás menos XML por favor. Jose María Arranz Santamaría (jmarranz). Profesor Asociado de la Universidad Politécnica de Madrid.
Sobre el autor
Abraha Abr aham m Otero Ote ro ([email protected]) es responsable de calidad y miembro de la junta de javaHispano. http://digital.revistasprofesionales.com
9
SOLO PROGRAMADORES nº 124
CANAL PANDA
Pharming, nueva técnica de fraude FERNANDO DE LA CUADRA
Los hackers están intentando, cada vez más, obtener beneficios económicos de sus actuaciones y del malware que crean.
Esquema del proceso de resolución de nombres cuando accedemos a los servicios del servidor de Panda Software.
SOLO PROGRAMADORES nº 124
10
Si hasta ahora uno de los fraudes más extendidos era el phishing, consistente en engañar a los usuarios para que efectúen operaciones bancarias en servidores web con el mismo diseño que un banco on-line, el pharming entraña aún mayores peligros que el phishing. Básicamente, el pharming consiste en la manipulación de la resolución de nombres en Internet, llevada a cabo por algún código malicioso que se ha introducido en el equipo. Cuando un usuario teclea una dirección (como puede ser www.pandasoftware.com), ésta debe ser convertida a una dirección IP numérica, como 62.14.63.187. Esto es lo que se llama resolución de nombres, y de ello se encargan los servidores DNS, siglas que corresponden a “Domain Name Server”. En ellos se almacenan tablas con las direcciones IP de cada nombre de dominio. A una escala menor, en cada ordenador conectado a Internet hay un fichero en el que se almacena una pequeña tabla con nombres de servidores y
direcciones IP, de manera que no haga falta acceder a los DNS para determinados nombres de servidor, o incluso para evitarlo. El pharming consiste en modificar este sistema de resolución de nombres, de manera que cuando el usuario crea que está accediendo a su banco en Internet, realmente está accediendo a la IP de una página web falsa. El phishing debe su éxito a la ingeniería social, aunque no todos los usuarios caen en estos trucos y su éxito está limitado. Y además, cada intento de phishing se debe dirigir a un único tipo de servicio bancario, por lo que las posibilidades de éxito son muy limitadas. Por el contrario, el pharming puede atacar a un número de usuarios de banca muchísimo mayor. Además, el pharming no se lleva a cabo en un momento concreto, como lo hace el phishing mediante sus envíos, ya que la modificación de DNS queda en un ordenador, a la espera de que el usuario acceda a su servicio bancario. De esta manera, el atacante no debe estar pendiente de un ataque puntual, como hemos mencionado antes. La solución para esta nueva técnica de fraude pasa, de nuevo, por las soluciones de seguridad antivirus. Las acciones necesarias para llevar a cabo el pharming necesitan efectuarse por alguna aplicación en el sistema a atacar (puede ser un fichero exe, un script, etc.). Pero antes de poder ejecutarse esta aplicación, debe llegar al sistema objetivo, evidentemente. La entrada del código en el sistema puede ser a través de múltiples vías, tantas como entradas de información hay en un sistema: el e-mail (la más frecuente), descargas por Internet, copias desde un disco o CD, etc. En todas y cada una de estas entradas de información, el antivirus debe detectar el fichero con el código malicioso y eliminarlo, siempre que se encuentre detectado como una aplicación dañina dentro del fichero de firmas de virus del antivirus. Desgraciadamente, hoy en día nos movemos en un escenario en el que el malware ha adquirido una velocidad de propagación muy elevada, y los creadores son más y ofrecen al resto de la comunidad hacker los códigos fuente para que introduzcan variaciones y puedan crear ataques nuevos. Los http://digital.revistasprofesionales.com
CANAL PANDA
Pharming, nueva técnica de fraude
laboratorios de virus no tienen tiempo suficiente para efectuar la detección y eliminación del malware para todos los nuevos códigos antes de que lleguen a propagarse en unos pocos PCs. A pesar de los esfuerzos y la mejora de los laboratorios, es humanamente imposible que se elabore una solución adecuada y a tiempo para algunos códigos que se propagan en cuestión de minutos. La solución para este tipo de amenazas no debe ser, al menos en un primer frente de protección, una solución reactiva, sino que deben instalarse sistemas mediante los cuales se detecten no los ficheros en función de firmas víricas, sino las acciones que se llevan a cabo en el ordenador. De esta manera, cada vez que se intente realizar un ataque al sistema de DNS del ordenador (como es el caso de las aplicaciones para pharming), sea reconocido el ataque y detenido, así como el programa que lo ha llevado a cabo, bloqueado. Sin embargo, existe un peligro añadido a esta nueva técnica de pharming, que reside en los servidores proxies anónimos. Muchos usuarios desean ocultar su identidad (su dirección IP) a la hora de navegar, por lo que utilizan servidores proxy instalados en Internet que llevan a cabo la conexión con la IP del servidor en lugar de la IP del cliente. clie nte. En el peor de los casos, uno de estos servidores proxy puede tener la resolución de nombres alterada, de manera que los usuarios que intenten entrar en su página bancaria (a pesar de que su sistema local está perfectamente asegurado) sean redirigidos por el proxy a una página con el mismo diseño y apariencia de su banco, pero falsa. También podríamos pensar, siendo más positivos, que el servidor proxy ha sufrido algún tipo de ataque que altere su sistema de resolución de nombres de dominio. En cualquiera de los casos, el problema del pharming se plantea como peligroso, aunque de muy fácil solución. Únicamente con sistemas capaces de detectar los cambios en la resolución de nombres de Internet en el ordenador y con sistemas para su bloqueo, podremos hacer frente a la avalancha de códigos maliciosos que nos espera y que intentan estafar a los usuarios.
Sobre el autor Fernando de la Cuadra ([email protected]) es editor técnico internacional de Panda Software (http://www.pandasoftware.com).
http://digital.revistasprofesionales.com
Los usuarios de banca on-line amenazados por un nuevo ladrón de contraseñas
El laboratorio anti-virus de Panda Software (PandaLabs) ha detectado recientemente la aparición de Searchmeup, el primer adware (o programa que muestra publicidad) que utiliza una vulnerabilidad de Microsoft para sustraer información de los usuarios. Los usuarios de banca on-line se ven expues- 2000/NT/Me/98, y permite ejecutar código arbitos a esta amenaza simplemente al navegar trario en el sistema. Puede ser aprovechada por por Internet. Este adware se introduce en las un atacante alojando un cursor o icono espemáquinas sin el consentimiento del usuario cialmente creado en una página web maliciosa, utilizando una vulnerabilidad denominada o en un mensaje de correo electrónico en forExploit/LoadImage. mato HTML. Para corregir este problema Una vez introducido en el ordenador cambia la Microsoft ha publicado la correspondiente página de inicio del navegador, dejando en su actualización, cuya instalación se recomienda. lugar la de un buscador que, cada vez que se Para más información, puede visitarse la direccarga, muestra popups que instalan spyware y ción http://www.microsoft.com/spain/technet/ dialers en el equipo como el troyano Tofger.AT, seguridad/boletines/MS05-002-IT.mspx los dialers Dialer.BB y Dialer.NO, y otro adware Ante el peligro que representa Searchmeup y denominado Adware/To Adware/TopConvert. pConvert. el troyano Tofger.AT, Panda Software recoInfectado el ordenador, cuando el usuario abre mienda extremar las precauciones y manteInternet Explorer, Tofger.AT se activa y si el ner actualizado el software antivirus. Los usuario visita uno de los 15 bancos on-line clientes de Panda Software ya tienen a su dismás importantes de España (páginas con posición las correspondientes actualizaciones conexiones seguras HTTPS) Tofger.AT captura- para la detección y desinfección de estos rá la contraseña utilizada para acceder a las nuevos códigos maliciosos. siguientes entidades bancarias: cajamadrid, Asimismo, los clientes de Panda Software ya bpinet, millenniumbcp, hsbc, barclays, tienen disponibles las actualizaciones para lloydstsb, halifax, autorize, bankofamerica, instalar las nuevas Tecnologías TruPrevent bancodevalencia, cajamar, portal.ccm, bancaja, junto junto con su antiv antiviru iruss y estar, estar, así, prote protegid gidos os caixagalicia, caixapenedes, ebankinter, caixasa- de forma preventiva frente a nuevos códigos badell, bes, banif, millenniumbcp, totta, banco- maliciosos. Por otro lado, para usuarios que mais, montepiogeral, bpinet, patagon, lacaixa, cuenten con otros antivirus del mercado, citibank, bbvanet, banesto, e-trade y unicaja. Panda TruPrevent Personal es la solución idóEl usuario infectado no es consciente de la nea, ya que es compatible y complementaria a existencia de Searchmeup a menos que: éstos y proporciona una segunda línea de defensa y una protección preventiva que Observe el cambio de la página de inicio de su navegador. actúa mientras el antivirus es actualizado, disminuyendo el riesgo de ser infectados. El lec Si se genera un error y se reinicia el ordenador en un minuto (lo cual puede no tor puede conocer más sobre las tecnologías ocurrir siempre). TruPrevent en http://www.pandasoftware.es/ truprevent. También puede mostrar pantallas de error de sistema (pantallazos azules). Para la detección y desinfección gratuita de La vulnerabilidad Exploit/LoadImage de la que los ordenadores, los usuarios pueden utilizar se aprovecha Searchmeup afecta a ordenado- el antivirus on-line Panda ActiveScan, dispores con sistema operativo Windows 2003/XP/ nible en http://www.pandasoftware.es. 11
SOLO PROGRAMADORES nº 124
ACTUALIDAD ACTUALI DAD
BEA entra en la red con Da Vinci CARLOS LAPARRA
Hablamos con Enrique Martín, Director de Tecnología de BEA Systems, sobre el proyecto Da Vinci y el mercado de las Telecomunicaciones.
Enrique Martín atendió muy muy amablemente la llamada de Sólo Programadores.
En el número anterior de Sólo Programadores se publicaba una noticia que seguramente habrá generado una larga lista de interrogantes en el lector. En dicha noticia, cuyo título fue “El proyecto Da Vinci”, se informaba del lanzamiento de un innovador con junto jun to de prod product uctos os por por par parte te de de BEA BEA Syste Systems ms,, agruagrupados todos ellos bajo el nombre en clave “Da Vinci”. Tal como se informaba en dicha noticia, esta nueva gama de productos va dirigida a la industria de las Telecomunicaciones, y su objetivo es permitir a las corporaciones corporacion es de este sector ampliar el actual abanico de servicios e incrementar sus beneficios mediante la creación, la gestión y la entrega de servicios móviles de una forma ágil y eficaz. Intrigados por este nuevo lanzamiento, y viendo que puede ser la piedra angular de cambios importantes en la forma de diseñar, implementar y desplegar nuevos servicios basados en las infraestructuras de Telecomunicaciones, hemos considerado de interés el mantener una charla con Enrique Martín, Director de Tecnología de BEA Systems, quien muy amablemente no ha dudado en responder a todas nuestras cuestiones. Esperemos que esta entrevista pueda servir para que el lector entienda el giro que está a punto de producirse en el sector de las Telecomunicaciones y, por lo tanto, las nuevas tecnologías que la gente de Tecnologías de la Información (TI) tendrá que asimilar en sus proyectos futuros. Sólo Programadores. Tradicionalmente, BEA ha ofrecido plataformas de software orientadas a todos los mercados e industrias. ¿Por qué estamos presenciando ahora el lanzamiento de un producto específico para el mercado de las Telecomunic Telecomunicaciones? aciones? Enrique Martín. BEA siempre ha perseguido una
oferta horizontal de middleware orientada a servidores de aplicaciones y control de proceso. Con Da SOLO PROGRAMADORES nº 124
12
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 existen estándares muy sólidos como por ejemplo J2EE; en cambio, el mundo de las Telecomunicaciones carece de ello, y por eso se construye sobre una tecnología distinta en cuanto al propósito, pero muy parecida en cuanto a la filosofía horizontal. BEA ha querido dar el salto y, sin salir del mundo de la oferta de infraestructura, ahora queremos ofrecer un producto de infraestructura muy particular para el sector de las Telecomunicaciones. S.PP. ¿Por qué, desde el punto de vista de BEA, el sector de las Telecomunicaciones necesita esta infraestructura particular que has mencionado? E.M. Como te he comentado, el objetivo que persi-
guen las corporaciones del sector de las Telecomunicaciones es llegar a estándares para el desarrollo de aplicaciones y servicios sobre sus redes, del mismo modo que en el sector de las TI se han alcanzado estándares del nivel de J2EE. En este sentido, la oferta de BEA particularizada en el sector de las Telecomunicaciones consiste en proveer a estas empresas de una infraestructura que ofrezca una convergencia total entre los protocolos estándares de la red y los estándares típicos del mundo de las TI. Aquí es importante entender que cuando mencionamos “red”, estamos haciendo referencia a toda la infraestructura de la red de Telecomunicac Telecomunicaciones iones (red de 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 necesario un cambio de estrategia. Uno de los factores que ha llevado a este punto al propio sector es el hecho de que los servicios se han construido pensando en la propia estructura de la red, quedando éstos localizados y aislados en los propios nodos de la red (servicios de voz, videoconferencia, gestión de tonos, etc.). En la medida en que los operadores de telefonía pretendan aumentar su facturación con servicios alternativos al de voz, como por ejemplo con http://digital.revistasprofesionales.com
ACTUALIDAD ACTUALI DAD
BEA entra en la red con Da Vinci
aplicaciones de datos, van a experimentar unos costes altísimos al implantar estos nuevos servicios con la filosofía actual, es decir, localizándolos en los nodos de la red. En estos momentos ya todos tenemos teléfono móvil, por ejemplo. Esto hace muy difícil el que una operadora pueda seguir creciendo con los servicios de voz, lo cual nos lleva a la conclusión de que los servicios y las aplicaciones de datos son el nuevo camino a explorar. Pero si la implantación de estos nuevos servicios tiene unos costes tan altos... ¿cuál es el futuro? La solución a esta tesitura pasa por aislar la capa de red (transporte) de la capa de servicio (aplicaciones) y en esta última poder desarrollar y desplegar aplicaciones con la velocidad y agilidad que las necesidades comerciales lo requieran. Con esto se conseguirá tener aplicaciones que podrán ser usadas por miles de empresas, puesto que se basarán en tecnologías de servidor estándares huyendo del carácter propietario de este tipo de redes. Retomando el hilo de la pregunta, la convergencia entre los estándares del mundo de las Telecomunicaciones y del mundo de las TI resulta necesaria para poder desarrollar aplicaciones que obtengan lo mejor de ambos sectores y poder ofrecer así al usuario 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 hablas del carácter propietario de las redes de Telecomunicaciones? E.M. La realidad actual es que si desarrolla-
mos una aplicación de datos para una operadora (por ejemplo para ofrecer un servicio de datos a sus usuarios finales), será prácticamente imposible que esta aplicación pueda ser adquirida por otra operadora, dado que cuando se desarrolla una aplicación de este tipo, puesto que se debe usar la infraestructura de la red de Telecomunicaciones, es necesario “descender” hasta los niveles de protocolos y estos, efectivamente, son propietarios. Por lo tanto, podemos afirmar que la naturaleza de las redes de Telecomunicaciones actuales supone un problema para la nueva orientación del mercado que comentaba antes. S.PP. ¿Cómo es posible superar esta dificultad? E.M. Precisamente en esta línea es en la que
estamos trabajando. Es necesario evolucionar esta red, introduciendo interfaces estándares http://digital.revistasprofesionales.com
En la figura adjunta puede verse la posición que ocupa el protocolo SIP en la pila de protocolos.
que permitan el uso de la propia infraestructura de la red con el objetivo de que los servicios que se desarrollen sobre ella no le sean dependientes. S.PP. ¿Podrías poner un ejemplo, para entender claramente el problema que supone 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éfono móvil como si es enviado desde una aplicación web, a la postre ambos medios deberán consumir el servicio de una operadora de Telecomunicaciones. Efectivamente, el operador exhibe un interfaz mediante el cual nosotros podremos darle el mensaje y éste servicio lo convertirá en un SMS. Pero este operador deberá mandar el mensaje a través de un hardware que es propietario, puesto que ha sido subministrado por alguna de las principales empresas proveedoras de este tipo de equipos. Cada modelo de cada fabricante realiza esta acción de una manera distinta, luego estamos ante un problema únicamente solucionable mediante estándares. En este sentido, haré un paralelismo que será entendido rápidamente por cualquier programador. ¿Qué sucedía cuando no había APIs estándares para el acceso a bases de datos? Pues sencillamente que una aplicación escrita para un SGBD no podía de ninguna manera conectarse a otro SGBD. Así pues, lo que se consiguió entonces con la estandarización del acceso a bases de datos es algo parecido a lo que se está persiguiendo en la actualidad, pero aplicado a la infraestructura de las redes de Telecomunicaciones. S.PP. A lo largo de la entrevista está quedando clara la importancia que van a tener los estándares en la nueva orientación que va a tomar el mercado de las
Telecomunicaciones. ¿Qué estándares son esos? E.M. Efectivamente, son tres los estándares
más prometedores del mundo de las Telecomunicaciones, aquellos que permiten la comunicación de voz y multimedia: SIP, Parlay y JAIN. SIP (Session Initiation Protocol) es el protocolo de señalización para voz sobre IP, principalmente. Simplificando mucho diremos que, en el mundo de la telefonía, al establecer una llamada telefónica se están empleando dos circuitos de información. Uno se encarga de la señalización y el control de la llamada y el otro se encarga puramente de streaming del audio. Por lo tanto, en el mundo IP SIP será el protocolo encargado de establecer la llamada. Parlay es un protocolo cuyo objetivo es la homogeneización de la infraestructura de red, independientemente de quién sea el fabricante de esa infraestructura. Retomemos de nuevo el ejemplo del envío del SMS propuesto anteriormente. La problemática de hacer esto en una red propietaria desaparecería si pudiéramos usar la infraestructura de dicha red mediante interfaces estándares. En efecto, éste es el objetivo de Parlay. Y, por último, comentar de forma muy resumida que JAIN representaría un servidor de aplicaciones situado dentro de la propia infraestructura de la red y que permitiría conseguir una “red inteligente”. S.PP. En este escenario, ¿qué solución ofrece BEA para las empresas del sector de las Telecomunic Telecomunicaciones? aciones? E.M. Básicamente, y de forma resumida,
desde BEA se hace una apuesta firme por la convergencia a la que hacíamos alusión al principio de esta conversación. En este sentido, BEA pretende integrar en su oferta de infraestructura a los tres estándares del mundo de las Telecomunicaciones (SIP, Parlay 13
SOLO PROGRAMADORES nº 124
ACTUALIDAD ACTUALI DAD
Un SIP Servlet muy básico public 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 clase de detalles los objetivos que persigue el proyecto Da Vinci.
y JAIN), ofreciendo así una plataforma optimizada para las empresas de este sector. En la actualidad, BEA ya tiene una oferta completa para las compañías de Telecomunicaciones, conocida bajo el nombre de WebLogic Service Delivery, que incluye BEA WebLogic Communications Platform, BEA WebLogic Platform (Portal, Integration, App Server, Liquid Data Security & Workshop), BEA Tuxedo, BEA MobileAware Interaction Server, soporte especializado para servicios y soporte de empresas de Telecomunicaciones, etc. S.PP. Entonces, ¿qué es el proyecto Da Vinci?? Vinci E.M. Da Vinci es el nombre en clave de un pro-
yecto interno de doce meses de duración de BEA. Da Vinci representa, precisamente, el compromiso de BEA para suministrar una familia de productos integrados, que deben facilitar el desarrollo y despliegue de aplicaciones basadas en las redes de Telecomunicaciones y a la vez en las Tecnologías de la Información. Más concretamente, el producto que da sentido al proyecto Da Vinci y que BEA ha lanzado recientemente es BEA WebLogic Communications Platform. En efecto, BEA WebLogic Communications Platform es una suite de tecnologías integradas basada en estándares, diseñada para ayudar a las compañías de Telecomunicaciones a incrementar la productividad de sus negocios, mejorando su capacidad para crear, distribuir y gestionar voz convergente para innovadoras redes de Telecomunicaciones. SOLO PROGRAMADORES nº 124
14
Es importante entender que BEA WebLogic Communications Platform se compone de dos productos: BEA WebLogic SIP Server y BEA WebLogic Network Gatekeeper. BEA WebLogic SIP Server es un servidor de aplicaciones J2EE con soporte de SIP. Esto significa que podremos seguir desplegando nuestra aplicación en BEA WebLogic SIP Server, puesto que como servidor J2EE, soporta 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 protocolo SIP. Existen otras soluciones para el uso de SIP, pero la de BEA es la única que funciona encima del servidor de aplicaciones, de modo que con esta solución es posible mantener la infraestructura de aplicaciones de la corporación (EJBs, servicios web, etc.) para mantener nuestra lógica de negocio, y agregar aquí los servicios consumibles de la red de Telecomunicaciones mediante el protocolo SIP. Queda claro entonces que es aquí donde obtenemos la tan famosa convergencia entre la lógica de la aplicación y los servicios que ofrece la red de Telecomunicaciones. Por su parte, BEA WebLogic Network Gatekeeper es una infraestructura que permite ofrecer los servicios de red de la empresa (expuestos por BEA WebLogic SIP Server) a los agentes consumidores, pero agregando un componente restrictivo basado en políticas de seguridad y de acceso, en función de nuestras reglas de negocio. S.PP. ¿Sería posible apuntar algún ejemplo del tipo de aplicaciones que podríamos desplegar en BEA WebLogic SIP Server? E.M. Por supuesto. Es necesario entender que
el protocolo SIP está pensado para tener un control de la llamada (señalización y establecimiento). Veamos, técnicamente, cómo esto es posible. En el mundo de la web, cuando desde un navegador invocamos “http://www...” estamos accediendo a un servidor web, el cual nos enviará un documento HTML. En el mundo m undo SIP, bastará con marcar desde nuestro teléfono IP
el número con el que queremos establecer la llamada y el propio terminal enviará algo del estilo “sip://numero_de_telefono”, viajando esto por la red de Telecomunicaciones como si de una petición HTTP se tratara. Lo que ocurre es que esta petición nunca será tratada por un servidor web, sino por un servidor SIP. En efecto, aquí entrará en acción nuestro Servlet ejecutándose desde nuestro contenedor de SIP Servlet. Desde él, podremos acceder a la información del número que realiza la llamada, el número destino, etc. Por lo tanto, si podemos tener en nuestro servidor de aplicaciones el control de la llamada que desea efectuar el cliente, las acciones a realizar pueden ser tantas como seamos capaces de ingeniar. Por ejemplo, imaginemos que queremos construir un servicio de prepago. Únicamente tendremos que recibir la llamada, identificar a nuestro cliente, comprobar si dispone de crédito para efectuar la llamada y proceder en consecuencia, es decir, establecer la llamada o denegarla. De igual modo, podríamos construir un servicio de redirección de llamadas en caso de que la llamada se efectúe a una hora determinada o, por ejemplo, establecer que si en el momento de producirse la llamada el teléfono destino se encuentra ocupado, se deberá realizar la llamada inversa cuando la línea quede libre, etc. Pasando a temas más avanzados, podríamos pensar en la construcción de centralitas virtuales alojadas en nuestro servidor de aplicaciones o, por ejemplo, en incluir en los formularios de nuestra aplicación web un botón que sirviera para que el usuario pudiera solicitar una llamada por parte de la empresa para aclarar cualquier duda sobre el propio formulario, todo esto en tiempo real. Como ha podido verse, BEA WebLogic SIP Server es capaz de unir el mundo de las Telecomunicaciones con el mundo de TI, ofreciendo una variedad de servicios y aplicaciones realmente curiosas. http://digital.revistasprofesionales.com
ACTUALIDAD ACTUALI DAD
Sun Certified Enterprise Arc A rchi hittec ectt fo forr J2 J2EE EE JAVIER CANO MEDINA (Arquitecto J2EE SCEA)
En este artículo vamos a tratar de detallar en qué consiste la certificación como arquitecto J2EE de Sun, las distintas pruebas que la componen, proceso de inscripción y posibles fuentes de documentación para prepararnos este examen. Introducción El objetivo de la certificación como arquitecto J2EE es la evaluación de los conocimientos del aspirante acerca del diseño de arquitecturas software en el ámbito de los sistemas empresariales, especialmente centrados en entornos Internet/intranet y sobre la plataforma J2EE. Esta certificación evalúa una serie de aspectos teóricos y prácticos que veremos más adelante, como pueden ser modelado con UML, patrones, EJBs o seguridad, entre otros. Tal y como se define en el libro de preparación de esta certificación de Mark Cade y Simon Roberts, el objetivo fundamental de una arquitectura software es la de cumplir los requerimientos de nego-
Página web en la que Sun informa sobre las notas de las certificaciones. certificaciones.
SOLO PROGRAMADORES nº 124
16
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 certificaciones ofertadas por Sun dentro de la plataforma Java. La obtención de esta certificación no presenta ningún requisito previo, es decir, no es necesario obtener ningún otro certificado Sun ni haber realizado ninguno de los cursos recomendados. De hecho, no es necesario un conocimiento exhaustivo de las APIs J2EE aunque si es recomendable el tener cierta experiencia 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 de ejecución. SCJP y SCJD están orientadas a la plataforma básica Java o J2SE. En el caso de las certificaciones SCWCD, SCBCD, SCDJWS junto con la certificación SCEA, que es la que nos ocupa, están centradas en la plataforma J2EE. En último lugar, la certificación SCMAD se orienta a dispositivos móviles o J2ME. Para todas las certificaciones, excepto para la de arquitecto (SCEA), es requisito imprescindible la obtención previa del certificado como Programador Java (SCJP). Desde un punto de vista profesional, la obtención de la certificación SCEA puede resultar beneficiosa tanto para la empresa como para el empleado. En el caso de la empresa, podrá incluir entre sus recursos disponibles un arquitecto certificado mientras que en el caso del empleado, supone un salto cualitativo en su historial profesional. Esta certificación se compone de tres partes, que se detallan en los apartados siguientes, una primera parte teórica sobre diferentes conceptos, un ejercicio práctico y una última prueba teórica acerca de nuestro ejercicio práctico. Es importante resaltar que todas las pruebas, tanto las teóricas como las prácticas, han de realizarse en inglés. http://digital.revistasprofesionales.com
ACTUALIDAD ACTUALI DAD
Sun Certified Enterprise Architect for J2EE
SCEA parte I: prueba teórica La primera parte de la certificación es una prueba teórica tipo test, compuesta por 48 preguntas. Es necesario obtener una nota igual o superior a un 68% para superar este examen, disponiéndose de 78 minutos para su realización. Es importante comentar que en todas las preguntas que componen el test se indica el número de respuestas correctas, lo que a la hora de realizar la prueba supone una ayuda bastante importante. Esta prueba, al igual que la tercera parte de la certificación, se realiza en un centro Prometric autorizado, utilizando su equipamiento hardware y, lógicamente, sin poder utilizar ningún tipo de documentación para la realización del mismo. Una vez finalizada esta primera prueba, su corrección y la entrega de la nota es inmediata en el propio centro Prometric. Al mismo tiempo Sun proporciona una web (http://www. certmanager.net/sun_assignment) donde podemos consultar las notas de esta y otras certificaciones Sun. Tal y como se comenta en esta web, la actualización de los resultados se realiza transcurridos dos o tres días. Los objetivos del examen son: Conceptos básicos: En este apartado se trata de evaluar conceptos relacionados con la orientación a objetos y el lenguaje de modelado UML. Impacto de la herencia, encapsulado de funcionalidad y utilización de interfaces en la definición de arquitecturas software, así como dibujo e interpretación de diagramas UML. Arquitecturas: Los conceptos a evaluar en este apartado están relacionados con la identificación de las diferentes características de las arquitecturas en dos capas, tres capas y n-capas, así como su impacto en los requerimientos a nivel de servicio que comentábamos anteriormente. Reconocer el impacto de una arquitectura J2EE en estos mismos requerimientos de nivel de servicio e identificar posibles puntos débiles de una arquitectura software dada. Conectividad con sistemas heredados: El objetivo de esta sección es evaluar la capacidad de determinar cuál es el método más adecuado de acceso a un sistema heredado (Sistema Mainframe, ERP, etc.) desde una aplicación J2EE. Tecnología EJB: Los objetivos a evaluar en este apartado están relacionados con la utilización de Enterprise JavaBeans: clases e http://digital.revistasprofesionales.com
Esquema con las certificaciones certificaciones de Sun.
interfaces que componen la definición de un EJB, diferencia diferenciass entre Stateful y Stateless Session Bean, así como entre Entity Beans y Session Beans, beneficios y coste de la utilización de la Persistencia Manejada por el Contenedor (CMP) frente a la Persistencia Manejada por el Bean (BMP), descripción del comportamiento transaccional de un EJB, seguridad y utilización de DAOs en el acceso a datos desde EJBs. Contenedor EJB: Comportamiento del contenedor EJB a la hora de definir el ciclo de vida de los EJB, así como los diferentes mecanismos utilizados por el contenedor para aumentar la escalabilidad y rendimiento de las aplicaciones J2EE como puede ser la definición de pools de instancias o la activación/pasi activación/pasivación vación de EJBs. Protocolos: Definir las diferentes características de los protocolos HTTP, HTTPS, IIOP y JRMP, así como identificar el protocolo más apropiado en un escenario concreto y determinar los posibles problemas derivados de la presencia de un firewall en un entorno concreto y utilizando un protocolo determinado. Aplicación de tecnologías J2EE: Definir los aspectos de una aplicación susceptibles de ser implementados mediante la tecnología J2EE, así como mediante la utilización de EJB. Patrones de diseño: Seleccionar el patrón de diseño (GoF) más adecuado para ser utilizado en un escenario concreto, reconocer los beneficios de la utilización de los patrones y determinar el patrón a partir del diagrama UML correspondiente. Mensajería: En este apartado se evalúa la correcta identificación de los escenarios en los que la utilización de la mensajería resuelta adecuada, así como reconocer los
beneficios de la mensajería síncrona y asíncrona. Determinar, dado un escenario, si la utilización de la mensajería resulta adecuada. Internacionalización de aplicaciones: Determinar los tres aspectos específicos de una aplicación que resulta necesario modificar para lograr su internacionalización. Conocer las clases fundamentales involucradas en este proceso. Seguridad: Conocer las restricciones de seguridad aplicadas a la ejecución de Applets en los navegadotes web y dado un escenario específico, determinar la localización correcta de la implementación de las características de seguridad, así como seleccionar la tecnología más adecuada. Algunos conceptos importantes en este apartado son SSL, Certificados y Firma Digital, Firewalls y DMZ, etc.
Ejemplos de preguntas A continuación se muestran algunos ejemplos de preguntas de esta primera parte de la certificación. Además en el libro de Mark Cade/Simon Roberts también se incluyen ejemplos 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 you need the following components: (A) A Home interface, A Remote Interface and a class that implements either the SessionBean or EntityBean interfaces.
17
SOLO PROGRAMADORES nº 124
ACTUALIDAD ACTUALI DAD
Página web de Sun con información de las certificaciones Java. Java.
(B) A Home interface and a class that implements either the SessionBean or EntityBean interfaces. (C) A Remote interface and a class that implements either the SessionBean or EntityBean interfaces. (D) A Remote interface and a class that implements the EnterpriseBean interface. 3. Which statements are true? ejbPassivate() ate() is called prior to passiva(A) ejbPassiv 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 of classes for Messaging. (A) TRUE (B) FALSE 5. What are the benefits of asynchronous 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 una serie de libros y direcciones web que pueden resultar de ayuda en la preparación de esta primera parte de la certificación.
SOLO PROGRAMADORES nº 124
18
SCEA parte II: ejercicio práctico El objetivo de este ejercicio práctico es, una vez demostrados una serie de conocimientos teóricos sobre arquitecturas software y J2EE mediante la superación de la primera parte de la certificación, comprobar si el aspirante es capaz de aplicar estos conocimientos a la resolución de un supuesto práctico. Una vez superada la primera parte de la certificación y realizado el pago de este ejercicio práctico, podemos descargar la prueba desde la web http://www.certmanager.net/ sun_assignment. No existe restricción en cuanto al tiempo que puede transcurrir entre la realización de la primera parte y el abono de la matrícula de esta segunda prueba. En el fichero JAR descargado se incluye en formato HTML la descripción del problema planteado, la documentación necesaria para su resolución así como el formato de la solución a entregar y los distintos aspectos a tener en cuenta en su corrección. Esta solución debe presentarse también en formato HTML. Es obligatorio que al solución esté compuesta por diagramas de clases, diagramas de componentes y diagramas de secuencia y/o colaboración, no especificándose el número de diagramas de cada tipo que debe presentarse. También es recomendable que se incluya documentación explicando los planteamientos previos que hemos tenido en cuenta a la hora de resolver el ejercicio, así como una explicación detallada de nuestra solución.
Según se especifica en la documentación que acompaña al ejercicio práctico, los diagramas de clases tienen un peso igual a 44 en la nota final, donde la correcta utilización del lenguaje UML tiene una nota máxima de 10 mientras que la resolución de los requerimientos expresados en el ejercicio tiene una nota máxima de 34. En el caso de los diagramas de componentes la proporción es la misma, 10 frente a 34 para un total de 44. En el caso de diagramas de secuencia/colaboración la nota total máxima es 12, otorgándose una nota máxima de 3 a la correcta utilización del lenguaje UML, mientras que el cumplimiento de los requerimientos del sistema se puntúa como máximo con una nota de 9. Una vez que demos por concluido nuestro ejercicio, para la entrega de la solución nos dirigiremos a la web de Sun ya comentada donde deberemos tener habilitado un botón “Upload” que nos permitirá enviar la solución para su evaluación. Esta solución debe enviarse en formato JAR y el nombre del fichero a enviar debe contener el identificador del candidato, suministrado por Sun al realizar un primer examen de certificación Java. Para la preparación de esta segunda parte de la certificación, puede resultar especialmente interesante el libro “Designing Enterprise Applications 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 en 4 preguntas sobre la forma en que hemos resuelto el ejercicio práctico de la segunda parte, siendo necesario argumentar nuestras decisiones a la hora de definir la arquitectura de nuestra solución. El tiempo disponible para su realización es de 90 minutos y, al igual que la primera parte de la certificación, esta prueba se tiene que realizar en un centro Prometric, previa adquisición del vouncher correspondiente y concertada la prueba en dicho centro. La nota obtenida en esta tercera parte es la combinación de la evaluación del ejercicio práctico y de esta tercera prueba. El proceso de corrección dura entre cuatro y seis semanas, pudiéndose consultar el resultado de la misma en la web anteriormente citada. http://digital.revistasprofesionales.com
ACTUALIDAD ACTUALI DAD
Sun Certified Enterprise Architect for J2EE
Códigos de las pruebas que componen la certificación de arquitecto J2EE A la hora de afrontar esta última prueba, no existe ninguna bibliografía que debamos revisar, siendo importante, por supuesto, haber resuelto el ejercicio práctico por nuestros propios medios y que no haya transcurrido demasiado tiempo entre la finalización del ejercicio práctico y la realización de esta última prueba. Una vez superadas las tres pruebas y transcurridas algunas semanas, Sun se encarga de enviar el certificado como arquitecto J2EE mediante envío postal.
Proceso de Inscripción El proceso de inscripción en cada uno de los exámenes es siempre el mismo. Como primer paso, debemos ponernos en contacto con Sun por teléfono (902 210 412) o por correo electrónico ([email protected]) para confirmar las cantidades a abonar para cada una de las pruebas ya que éstas pueden cambiar, además en el caso de particulares no es necesario el pago del IVA de cada una de las pruebas. Una vez confirmadas las cantidades, procederemos a realizar la transferencia de la cantidad correspondiente a la cuenta indicada por Sun y haremos llegar el justificante del pago mediante fax o correo electrónico. En el caso de la primera y tercera prueba, recibiremos en la dirección que indiquemos el vouncher que utilizaremos para concertar el examen en un centro Prometric autorizado. En el caso del ejercicio práctico no recibimos vouncher ya que no debemos realizarlo en ningún centro autorizado. En los tres exámenes sí recibiremos la factura correspondiente. A la hora de concertar el examen con el centro Prometric, se nos solicitará el vouncher enviado por Sun, siendo recomendable que confir-
Nombre de la prueba Sun Certified Architect for J2EE – Part I
CX-310-051
Sun Su n Cer Certi tifi fied ed En Entt Arc Archi hite tect ct fo forr Jav Javaa J2E J2EEE te tech ch.,., As Assi sign gnm men entt
CXX-33100-3300 00A A
Sun Certified Architect for J2EE – Part III Sun Certified Enterprise Architect for J2EE Technology, Assignment Resubmission
CX-310-061
memos que no es necesario abonar ninguna cantidad extra para la realización de la prueba. En el caso de no superar la segunda/tercera parte del examen, existe la posibilidad de volver a enviar el ejercicio práctico para que vuelva a ser evaluado, no siendo necesaria la realización de la tercera parte del examen.
Bibliografía Algunos libros recomendables para la preparación de esta certificación se detallan a continuación: Sun Certified Enterprise Architect for J2EE Technology: Study Guide , por Mark Cade/Simon Roberts. Sun Microsystems Press. Enterprise Applications Designing with the J2EE Platform, Second Edition, por Inderjeet Singh, Beth Stearns, Mark Johnson, and the Enterprise Team. Disponible en la web de Sun (http://www.sun.com). Distilled, por Martin Fowler, UML Kendall Scott. Addison Wesley. Applying UML and Patterns: An Intro to OOA/D and the Unified Process , por Craig Larman. Prentice-Hall. JavaBeans , por Richard Enterprise Monson-Haefel, O’Reilly & Associates.
Página web con información sobre la plataforma J2EE.
http://digital.revistasprofesionales.com
Código
CX-310-300R
Dessign Patterns: Elements of Reusable Object-Oriented Software, por Gamma et Al. Addison-Wesley. Core J2EE Patterns: Best Practices and Design Strategies, por Deepak Alur, John Crupi, Dan Malks. Sun Microsystems Press. EJB Design Patterns, por Floyd Marinescu. Wiley Computer Publishing, disponible en la web http://www.theserve http://www.theserverside.com. rside.com. Por otro lado, en Internet existen multitud de páginas donde es posible obtener información relativa, especialmente, a la primera parte 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=26 Páginas con Simuladores del Examen SCEA parte I: http://www.ianswebpage.com/cert/scea/ scea.htm http://prasks.webahn.com/ http://www.javacoding.net/certification/ mocks/index.html
Buscador de centros Prometric.
19
SOLO PROGRAMADORES nº 124
DISPOSITIVOS MÓVILES
Juegos de calidad comercial en J2ME (III) Uso de APIs adicionales ALBERTO GUTIÉRREZ MARTÍNEZ (Ingeniero en Informática y co-fundador de Flag Solutions) FRANCISCO JOSÉ GARCÍA PEÑALV PEÑALVO O (Profesor titular del departamento de Informática y Automática de la Universidad de Salamanca)
Como se está viendo a lo largo de este curso, el API de Nokia ofrece un conjunto muy avanzado de posibilidades. En esta tercera entrega estudiaremos, entre otras cosas, el control de la luz de la pantalla, la gestión del sonido, el acceso a la cámara de fotos del teléfono y el envío de SMS.
Introducción En la entrega anterior de este curso terminamos presentando la API propietaria de Nokia, centrándonos en todo lo que a nivel gráfico hacía referencia. En esta tercera entrega del curso continuaremos profundizando en esta importante API para descubrir qué más aporta a MIDP 1.0. Concluiremos este artículo con otras dos APIs opcionales, la Mobile Media API (veremos un MIDlet que accede a la cámara de nuestro teléfono), y la Wireless Messaging API (con la que haremos un envío de un SMS desde nuestro programa).
Continuando con la Nokia UI API
Hacer una foto o enviar un SMS son acciones fáciles de hacer con el API de Nokia
SOLO PROGRAMADORES nº 124
20
Detección de teclado Para detectar las pulsaciones de teclado a bajo nivel no necesitamos usar explícitamente la Nokia UI API, ya que MIDP 1.0 (véase la referencia 1) nos proporciona funcionalidad suficiente en este sentido. Sin embargo, vamos a ver en este apartado algunas aportaciones de esta API a la detección de teclado. Para este fin, empezaremos viendo el uso de la clase “Canvas”, que es la que en MIDP 1.0 incorpora las funciones relacionadas con este aspecto: keyPressed(int ssed(int keyCode keyCode): ): Evento que se keyPre levanta al pulsar una tecla (o detecta la pulsación continuada de la misma).
keyRepeated(int keyCode): Evento que se levanta mientras mantengamos pulsada una tecla. No lo utilizaremos porque se consigue una respuesta muy lenta del teclado. Como veremos en breve, usaremos otro enfoque para detectar una pulsación continuada de teclado. keyReleased(int sed(int keyCode) keyCode):: Evento que se keyRelea levanta al dejar de pulsar una tecla. pointerPressed(int x, int y): Evento que se levanta en terminales con pantalla táctil al pulsar con el lápiz. pointerDragged(int x, int y): Evento que se levanta en terminales con pantalla táctil al arrastrar el lápiz por la pantalla. Se levanta siempre, como es lógico, después de un evento “pointerPressed”. pointerReleased(int x, int y): Evento que se levanta en terminales con pantalla táctil al levantar el lápiz. Como no estamos programando para terminales con pantalla táctil no hablaremos de los tres últimos métodos, que, por otra parte, no entrañan ninguna dificultad en su uso. Observaremos que los tres métodos de detección de teclado reciben un parámetro llamado “KeyCode”. Para facilitar la portabilidad de las aplicaciones J2ME, la clase “Canvas” tiene un método que nos traduce ese “KeyCode” a teclas relacionadas con una acción típica de un juego; las llamadas “Game Actions”. Con esto se consigue que un terminal al ejecutar nuestro juego se encargue de “mapear” las teclas por nosotros y que, por ejemplo, un usuario use en nuestro juego la tecla que el fabricante ha estimado más oportuna para disparar, o las teclas de dirección para mover al personaje. El método que nos provee esta traducción es:
public int getGameAction(int keyCode)
Este método nos devuelve un entero que deberemos comparar con las constantes de la clase “Canvas” para saber qué tecla se pulsó tal y como se aprecia en el listado 1. En el código de este primer listado podemos observar cómo estamos detectando la pulsación http://digital.revistasprofesionales.com
DISPOSITIVOS MÓVILES
Juegos de calidad comercial en J2ME (III) LISTADO 1
simultánea de la tecla de disparo y de una tecla de dirección. No tiene sentido detectar la pulsación simultánea de dos teclas de dirección porque en los terminales telefónicos no se pueden pulsar a la vez (salvo en el nuevo Nokia N-Gage QD). Como vemos, aunque recogemos las pulsaciones en los eventos “keyPressed” y “keyReleased”, no respondemos a su pulsación hasta el método “moverJugador”, que forma parte de nuestro “game loop” del que hablaremos en próximos artículos. Si, como es nuestro caso, queremos usar la clase “FullCanvas” de Nokia que vimos en el artículo anterior para poner nuestros juegos a pantalla completa, como ya sabemos no podemos usar ni “addCommand” ni “setCommandListener”. Esto implica que ahora las teclas que normalmente se usaban para manejar estas órdenes en la clase “Canvas” (las llamadas “soft keys” de Nokia), se puedan detectar con la clase “FullCanvas” (con las “Game Actions” de la clase “Canvas” no es posible). Nuestro juego necesitará ser capaz de saber cuándo el usuario pulsa las “soft keys” por ejemplo para pausar el juego y mostrar el típico menú que permita salir del juego o cambiar configuraciones mientras el juego ya está empezado. La clase “FullCanvas” añade nuevas teclas a las “Game Actions” adicionales a las de la 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.
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 tecla else 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; } }
Si no vamos a necesitar que nuestro juego detecte las “soft keys” podemos usar sin problemas el mismo código que hemos visto en
Figura 1. Mapeado de teclas de un 3650 con “FullCanvas”. “FullCanvas”.
http://digital.revistasprofesionales.com
Detección de teclas con MIDP 1.0 estándar
el listado 1. En cambio si, como es usual, estamos obligados a detectarlas, es muy recomendable cambiar nuestro código por el que se presenta en el listado 2. Hay un par de cosas a resaltar en el código de este segundo listado. En primer lugar, ya no estamos usando la función “getGameAction()”. Si la usáramos comprobaríamos que no detectamos en el switch ninguna tecla correspondiente a las constantes definidas en la clase “Canvas”. Por otro lado, también debemos fijarnos en que para detectar el disparo estamos usando la constante “KEY_NUM2”, correspondiente a la tecla del número 2 de nuestro teléfono. La razón es que, salvo en la N-Gage, en el resto de teléfonos de la serie 60 no se puede simultáneamente pulsar la tecla de disparo y una dirección. Si nos queremos olvidar del problema de teclados tan distintos entre sí, es recomendable incorporar a nuestro juego jue go un un módul móduloo de con config figura uració ción n de tec teclad ladoo para que el usuario lo ponga a su gusto, y almacenar su configuración mediante RMS (Record Management System, véase el artículo “Persistencia de datos con J2ME” en el número 119) en el teléfono.
21
SOLO PROGRAMADORES nº 124
DISPOSITIVOS MÓVILES
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 tecla else 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;
Figura 2. MIDlet de vibración y backlight. backlight.
Vibración Vibraci ón y control de luz de pantalla pantalla Seguramente el lector apasionado de los juegos en los móviles habrá observado cómo muchos jueg ju egos os vi vibr bran an cu cuan ando do,, po porr ej ejem empl plo, o, nu nues estr traa na nave ve se golpea con un objeto, o cómo la pantalla parpadea 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 UI API). Vamos a ver un ejemplo en el que se usan algunos métodos sencillos que nos permiten controlar la vibración y la luz del teléfono. Los métodos relacionados con vibración y luz pertenecen a la clase “DeviceControl” y son todos estáticos. Son los siguientes: flashLights(lo flashLi ghts(long ng dura static void tion): La luz del móvil parpadeará durante los milisegundos que se le indiquen en el parámetro “duration”. “duration”. setLights(in setLig hts(intt num, int static void level): En la mayoría de los casos sólo podremos encender y apagar la luz trasera de la pantalla del móvil. En algunos terminales podremos elegir sobre qué luz actuar (con el parámetro “num”), y qué nivel de luminosidad tendrá. static void startVibra(int freq, long duration): Hace vibrar el móvil a la fre-
SOLO PROGRAMADORES nº 124
22
cuencia elegida durante el tiempo elegido. Cuando llamamos a esta función no se queda esperando a que acabe la vibración sino que internamente crea un hilo que la controla, por lo que podremos simultáneamente realizar otra acción mientras el teléfono sigue vibrando. Para una stopVibra(): static void vibración antes del tiempo para el que se programó. En el listado 3 mostramos el código fuente de un MIDlet que usa estos métodos y que tiene el aspecto que muestra la figura 2.
¡Advertencia! Si tienes un teléfono de la serie 60 de Nokia seguramente te habrás dado cuenta de de que los juegos Java nunca tienen la opción de vibración. La razón no es otra que la falta de soporte para esta funcionalidad de la serie 60. Si pruebas el ejemplo en el emulador de la serie 60 verás que no da ningún fallo pero simplemente no ocurre nada. Lo mismo pasa con la luz trasera.
Sonido Para reproducir sonido con MIDP 1.0 en un teléfono de la serie 60 tenemos dos opciones: usar la Nokia UI API o la Mobile Media API (JSR-135)
Figura 3. Aplicación de capacidades capacidades sonoras en ejecución. ejecución.
(salvo en el Nokia 7650 que no soporta esta API). Las clases relacionadas con el sonido en MIDP 2.0 son un subconjunto de la Mobile Media API, que será tratada en el siguiente apartado, sin embargo, para la mayoría de los terminales Nokia que no soporten MIDP 2.0 sólo tendremos como opción usar la Nokia UI API.
¡Advertencia! En cualquier teléfono Nokia compatible con MIDP 2.0 no deberemos usar las clases de la Nokia UI API que se usen para el mismo fin que las que existan en MIDP 2.0. Este es el caso, por ejemplo, de las clases relacionadas con el sonido. En un 6600, por ejemplo, Nokia no asegura que la clase “Sound” de la Nokia UI API funcione correctamente. Lo mismo ocurre con otras clases de esta API que han sido declaradas “Deprecated” “Deprecated”..
Cuando utilizamos la Nokia UI API, nos tenemos que limitar a 3 formatos: WAV: Formato binario (array de bytes). Smart Messaging Ringtones: Formato binario (array de bytes). dados por por su fre Tonos simples: Vienen dados cuencia y duración. http://digital.revistasprofesionales.com
Juegos de calidad comercial en J2ME (III) LISTADO 3
public class Principal extends MIDlet implements CommandListener { List myScreen; Command vibrar,flash,luzTrasera; boolean luzOn=true; public Principal() { super(); }
protected void pauseApp() {} protected void destroyApp(boolean arg0) throws MIDletStateChangeException {} public void commandAction(Command c, Displayable d) { if (d == myScreen) { if (c == List.SELECT_COM MAND) { 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; } } } } }
http://digital.revistasprofesionales.com
Este método, que en la documentación aparece declarado como “static”, en la práctica no lo es y debemos instanciar un objeto de la clase “Sound” para poder utilizarlo. Además, y mucho más importante, es necesario saber que este programa dará un error irrecuperable cuando se ejecute dicho método en cualquier teléfono de la serie 40 developer platform 1.x. El programa del listado 4 tiene el aspecto que se ilustra en la figura 3 al ejecutarse.
¡Advertencia!
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); }
Sin embargo, cada terminal Nokia puede ser compatible o no con estos tres formatos. Cada terminal es un “mundo” y encontraremos teléfonos como el Nokia 6230 que puede reproducir el formato MP3 de forma nativa y, sin embargo, no soporta este formato desde aplicaciones Java. Para saber qué formatos son compatibles y el número de sonidos concurrentes que se pueden utilizar, la clase “Sound” de Nokia tiene varios métodos a tal efecto: static int getConcurrentSoundCount(int type): Devuelve el número de sonidos
DISPOSITIVOS MÓVILES
concurrentes que se pueden reproducir del tipo dado. Normalmente, sólo se podrá reproducir un sonido a la vez. getSupportedFormats(): static int[] Devuelve una matriz con todos los formatos compatibles. En el listado 4 se puede apreciar cómo se utilizan estos métodos. En este programa se muestran por pantalla todos los formatos de audio que podremos usar en J2ME para el terminal. Hay que llamar la atención sobre una línea del programa: int[] formatos= miSnd.getSupportedFormats();
Hay que saber que las implementaciones de MIDP de Nokia suelen tener pequeñas variaciones entre sí, ¡incluso entre distintas versiones de software de un mismo modelo de móvil! Comprobaremos en numerosas ocasiones cómo algunos métodos de APIs soportadas no funcionan como se espera o simplemente no están soportados. Además, muchos de estos problemas no están documentados, y Nokia sólo da esta información a las empresas que forman parte del Foro Nokia Pro que es de pago. Sin embargo, Nokia pone de forma gratuita a disposición de los desarrolladores numerosas herramientas, documentación y foros en la dirección http://www.forum.nokia.com/main.html.
Todas las posibilidades sonoras de la Nokia UI API giran en torno a la clase “Sound” y a la interfaz “SoundListener”. Para comprender el uso de estas dos clases se ha codificado un nuevo programa, cuyas fuentes por motivos de espacio no se mostrará en su totalidad, aunque se puede encontrar en el CD-ROM que acompaña a la revista. No obstante, mostraremos las porciones de código más interesantes y las explicaremos a continuación. El programa que hemos desarrollado en esta ocasión nos permite reproducir los tres tipos 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.
Figura 4. Aplicación Aplicación de reproducción de audio en ejecución.
23
SOLO PROGRAMADORES nº 124
DISPOSITIVOS MÓVILES
LISTADO 4
El programa consta de dos clases, “Principal.java” y “Sonido.java”. La primera clase usa la clase “Sonido”, que es un envoltorio de la clase “Sound”, para reproducir los distintos tipos de sonido según la opción elegida. Además, implementa la interfaz “SoundListener” (además del “CommandListener”), con el que podremos detectar cuándo el estado de un sonido cambia, y mostrarlo en el título del “Form”. En el listado 5 se muestra el método “soundStateChanged()” de la clase “Principal.java” que gestiona los estados del sonido. Para que se levante el evento “soundState Changed” le hemos añadido un método a nuestra 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 destacar el array de bytes que se muestra en el listado 8, que no es más que un fragmento de una canción en formato “SmartRingTone” “SmartRingTone”.. De la clase “Principal” no destacaremos nada más. Nos fijaremos ahora en la clase “Sonido”. Esta clase como se ha señalado antes, es un wrapper o envoltorio de la clase “Sound” de Nokia que facilita su uso, sobre todo a la hora de crear el sonido. La clase tiene tres constructores, uno para cada tipo de sonido. Vamos Vam os a fijar fijarnos nos en el const constructo ructorr que crea un sonido WAV (véase el listado 9) porque es quizá la única parte del código que no es auto explicativa, sobre todo el método “getTamanno()”. El constructor primero llama a la función “getTamanno()” para conocer el tamaño del archivo WAV que se va a abrir y reservar memoria para una matriz de bytes del mismo tamaño. Posteriormente, lee el archivo a esa matriz y se la pasa al constructor de la clase “Sound” de Nokia. Quizá el método más interesante sea el “getTamanno()”. Para entenderlo hay que comprender 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 fragmento de la figura 5 tendría un tamaño de: 00 00 39 24 bytes; que es un número hexadecimal que transformado en decimal nos daría un tamaño de: 16.628 bytes (14,28KB). Este proceso es lo que hace el código del método “getTamanno()”. “getTamanno()”. Abrimos el archivo y
Figura 5. Cabecera de un fichero WA WAV.
SOLO PROGRAMADORES nº 124
24
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 40 Sound miSnd=new Sound(10,1000); int[] formatos= miSnd.getSupportedFormats(); if (formatos.length > 0) { for (int i=0;i
leemos el primer entero (32 bits) y lo almacenamos en la variable cabecera que no vamos a utilizar para nada. Habríamos leído
ya 52 49 46 46, ahora empezamos a leer byte a byte los cuatro bytes que codifican el tamaño: tam4=24, tam3=39, tam2=00 y tam1=00. Para terminar se invierte el orden de las variables y se transforma el número obtenido a decimal. El código del método se recoge en el listado 10. http://digital.revistasprofesionales.com
DISPOSITIVOS MÓVILES
Juegos de calidad comercial en J2ME (III) LISTADO 5
Fragmento de código que gestiona los estados del sonido
// Principal.java public void soundStateChanged(Sound s, int evento) { switch (s.getState()) { case Sound.SOUND_PLAYING : myScreen.setTitle(“Reproduciendo”); break;
case Sound.SOUND_UNINITIALIZED : myScreen.setTitle(“No Inicializ.”); break; } }
¡Advertencia! En el MIDlet no se ha incluido ningún tipo de control para que no se pueda seleccionar el WAV en un terminal que no soporta WAVs. Esto se ha hecho así para no mezclar conceptos con el MIDlet anterior. Por ello, si en un 7210 seleccionamos WAV, la aplicación dará un error irrecuperable.
Mobile Media API (JSR-135) Ya conocemos esta API estándar de SUN, que como vimos no está soportada en su totalidad por la serie 60 de Nokia. En MIDP 2.0 usaremos esta API, entre otras cosas, para reproducir sonidos en vez de usar APIs de los fabricantes tal y como vimos anteriormente. En este apartado vamos a mostrar un ejemplo de una de las múltiples posibilidades que tiene esta API, capturar una instantánea con la cámara del móvil. http://digital.revistasprofesionales.com
Fragmento de código que asigna el Listener de eventos de sonido con la clase Principal
// Sonido.java public void setEscuchador(SoundListener miEscuchador) { soundDriver.setSoundListener(miEscuchador); }
LISTADO 7
Fragmento de código que pasa la referencia de sí misma a la clase Sonido
// Principal.java sonWav.setEscuchador(this);
case Sound.SOUND_STOPPED : myScreen.setTitle(“Parado”); break;
Aunque habría otras maneras de cargar un archivo WAV, ésta quizá sea la más óptima, aunque como hemos visto implica conocer el formato binario del archivo. Una vez más comprobaremos que Nokia no nos avisa de determinados fallos. Si probamos este MIDlet, nos encontraremos con varias sorpresas: En el emulador del 7210 el Smart Ring Tone se oye pero mucho más rápido que en el terminal real, en el que la canción sí se oye como debiera. En el emulador de la serie 60, el Smart Ring Tone no se oye y ni siquiera se levanta el evento “SoundListener”. En el terminal real funciona perfectamente. En la documentación de la Nokia UI API se hace referencia a que se usen los Smart Ring Tones en vez de los Simple Tones. Y es que, aunque no lo pone en ninguna parte, los tonos simples no funcionan en la serie 60 developer platform 1.x (ni en el emulador ni en el terminal real). Sin embargo, en la serie 60 developer platform 2.0 sí que funcionan.
LISTADO 6
LISTADO 8
Fragmento de un array de bytes de un SmartRingTone
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 10
Cómo obtener el tamaño de un fichero WAV
private int getTamanno() { InputStream is; int tamanno=-1; try { DataInputStream datainputstream = new DataInputStream(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! Aunque las especificaciones del estándar hablen de que con la MMAPI (Mobile Media API) podemos reproducir y grabar audio y vídeo, sus posibilidades reales varían con cada móvil. Por poner un ejemplo, con el Nokia 3650 no se puede grabar ni audio ni vídeo, aunque sí reproducir ambos y capturar fotos. Con el Nokia 6600 ya se podía grabar audio aunque no vídeo. Se puede decir, por tanto, que en cada nuevo modelo de Nokia la implementación de la MMAPI va siendo más completa.
La aplicación que vamos a mostrar está basada en un documento de Nokia llamado “Camera MIDlet: A Mobile Media API example” y está disponible en el área de desarrolladores de su web en http://www.forum.nokia.com. La figura 6 muestra el diagrama de clases del MIDlet. Por motivos de espacio comentaremos las porciones de código más interesantes. El
En el ejemplo estamos obteniendo un array de bytes correspondiente a una imagen en formato BMP y del tamaño indicado. Hay que tener cuidado pues manipulando el tamaño de la imagen podríamos distorsionar la imagen. Además, no podremos especificar anchura o tamaño por separado, debemos especificar siempre los dos o tendremos un error. En cuanto al parámetro “encoding”, tenemos tres opciones de formato compatibles: PNG (Formato por defecto). BMP. JPEG. Figura 6. Diagrama UML del MIDlet de acceso a la cámara.
código completo del MIDlet se puede encontrar en el CD que acompaña a la revista. En el código mostrado en el listado 11 estamos simplemente accediendo a la cámara del móvil. Para ello estamos obteniendo un objeto “Placer” de un objeto “Manager”, y del objeto “Placer”, un objeto “VideoControl” que es con el que “jugaremos”. Lo más importante del listado 11 es el String que pasamos como parámetro al método “createPlayer()” que se llama “Capture Locutor” y hace referencia a dispositivos de captura. En la documentación de la MMAPI podemos ver una ampliación sobre los “Capture Locators” en la introducción a la clase “Manager”. En la práctica, si estamos programando para la serie 60 de Nokia, sólo podremos usar los “Capture Locutor” compatibles con el terminal en particular para el que estamos programando. Para saber qué “Capture Locators” son o no soportados por cada terminal, no nos queda qu eda más remedio que investigar en los foros de Nokia, así como en los documentos que ponen a nuestra disposición. Por ejemplo, si queremos saber cuáles son compatibles con un Nokia 6600, existe un documento en la web de Nokia llamado “Known Issues in_the Nokia 6600 MIDP 2.0”. Otra línea importante es en la que tomamos la instantánea: byte[] pngImage = videoControl. getSnapshot(null);
Sobre el parámetro que le pasamos al método “getSnapShot()”, en nuestro caso le hemos pasado “null”, con lo que obtendremos en la serie 60 de Nokia una imagen en formato PNG (Portable Network Graphics, véase la referencia 2) con un tamaño de 160x120 píxeles. Podremos “jugar” con este parámetro de la forma siguiente:
SOLO PROGRAMADORES nº 124
26
¡Advertencia! Nokia no recomienda capturar imágenes superiores a 240x180 a no ser que nuestro terminal sea un Nokia 6630 o similar. LISTADO 11
Figura 7. MIDlet de acceso a la cámara.
Cómo acceder a la cámara
//CameraCanvas.java player = Manager.createPlayer(“capture://video”); player.realize(); //Cogemos el VideoControl y lo mostramos por pantalla videoControl = (VideoControl)(player.getControl(“VideoControl”)); if (videoControl == null) { ... } else { videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO,this); ... }
Finalmente, para convertir la captura obtenida en una imagen normal, usamos el método “setImage()” de la clase “DisplayCanvas.java”, que se recoge en el listado 12. Simplemente estamos creando una imagen inmutable leyendo 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 la aplicación en funcionamiento en un 3650.
Wireless Messaging API (JSR-120) La WMA (Wireless Messaging API) es otra API opcional de SUN que nos permitirá enviar y recibir mensajes SMS (Short Message System) de texto y binarios. Los SMS de texto ya los conocemos todos, pero quizá los SMS binarios no sean tan conocidos a pesar de estar tan de moda últimamente. Los SMS binarios son mensajes que usan el protocolo Short Message
Service para enviar información que será interpretada sólo por algunos terminales. Por ejemplo, los logotipos de Nokia y los RingTones son ejemplos de información binaria que se pueden enviar en un SMS y que sólo será válida para un terminal Nokia o compatibles. Esta API nos abstraerá de la red que haya por debajo y como es lógico no nos importará si el SMS se enviará bajo GSM (Group Special Mobile o Global System for Mobile), CDMA (CodeDivision Multiple Access), etc. Es importante no confundir esta API con la Nokia SMS API, que es anterior en el tiempo a la WMA, y sólo fue soportada por el Nokia 3410. Sus características eran similares a las de la WMA salvo que tenía una funcionalidad muy parecida al Push WAP de MIDP 2.0 que no es objeto de estudio en la presente serie de artículos. La WMA es una API con pocas clases y sencilla de aprender si se parte de un ejemplo que http://digital.revistasprofesionales.com
Juegos de calidad comercial en J2ME (III) LISTADO 13
muestre el funcionamiento, por eso vamos a mostrar un ejemplo auto explicativo de cómo enviar un SMS desde nuestro MIDlet. Con el código del listado 13 se envía un SMS al teléfono (inexistente) 75186266 7518626611 de España. Afortunadamente, para evitar la existencia de MIDlets malintencionados que se dedicaran a enviar mensajes SMS indiscriminadamente, en el momento de ejecutarse el “send” nos aparecerá un mensaje de confirmación de la interfaz del teléfono para avisarnos de que se va a enviar un SMS, y podremos abortar el envío. Es importante saber que podremos enviar grandes extensiones de texto y no tener la limitación de los 160 caracteres de un SMS. La interfaz “MessageConnection” tiene un método para calcular el número de SMSs necesarios para enviar un texto dado (“numberOfSegments”), por si el usuario de nuestro MIDlet quiere calcular cuánto le va a costar el envío que nuestro MIDlet, y como hemos dicho antes, siempre en último término el usuario será quien tenga la última palabra para realizar o no el envío de información. Para poder enviar MMS ya existe una nueva especificación de WMA, la JSR-205. Aunque todavía deberemos esperar un tiempo a que esté implementada en los teléfonos Nokia.
Compilación y ejecución de los ejemplos Para compilar y ejecutar los ejemplos propuestos no será suficiente con el J2ME Wireless Toolkit de Sun, puesto que los fragmentos de código aquí propuestos usan la API específica para terminales Nokia. Las herramientas necesarias para probar los ejemplos incluidos en el CD-ROM son, el propio J2ME Wireless Toolkit de Sun (http:// java.sun java .sun.co .com/p m/produ roducts/ cts/j2m j2mewt ewtool oolkit/ kit/dow downlo nlo-ad-2_2.html) ad-2_2.h tml) y, además, además, el Nokia Developer Developer’s ’s Suite for J2ME (http://www.forum.nokia.com/main/ 0,6566,034-2,00.html). Ambos paquetes de software están a disposición del desarrollador y pueden descargarse libremente. En el caso del Nokia Developer’s Suite será necesario completar un proceso de registro y obtener así un número de licencia, necesario para la instalación. Todo este
proceso queda explicado en la página de descarga del producto. Una vez descargados ambos productos, se procederá a la instalación de J2ME Wireless Toolkit de Sun. Es posible que el lector ya tenga instalado este entorno, puesto que ha sido objeto de estudio en números anteriores de Sólo Programadores . Después se procederá a la instalación del Nokia Developer’s Suite, eligiendo la instalación “standalone” (opción por defecto). Después de superar la instalación de ambos productos, se procederá a la configuración de la herramienta KToolbar del J2MEWTK. Para ello, habrá que copiar el contenido de la carpeta “C:\Nokia\Devices” (de la instalación del Nokia Developer’s Suite) dentro de la carpeta “C:\WTK22\wtklib\devices” (de la instalación del J2MEWTK). Con esto, habremos añadido a nuestro entorno J2MEWTK los emuladores para los terminales Nokia (de los emuladores instalados sólo se garantiza el correcto funcionamiento del “Series_60_MIDP “Series_60_MIDP_Concept_ _Concept_ SDK_Beta_0_3_1_Nokia_edition”). Para ejecutar los ejemplos incluidos en el CDROM tendremos dos posibilidades, totalmente equivalentes. La primera, es copiar las carpetas que hay dentro del directorio “Proyectos” del CD-ROM en el directorio “C:\WTK22\apps” de nuestro J2MEWTK. Después, ejecutar la herramienta KToolbar y pulsar en “Open Project”. En la lista de proyectos, podremos ver los proyectos añadidos, puesto que cada una de las carpetas incluidas en directorio “Proyectos” del CD-ROM corresponde a un proyecto. Después de 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 ejecutar los ejemplos consiste en crear nosotros mismos el proyecto. Para ello, habrá que pulsar
en “New Project” de KToolbar y nombrar el proyecto, para luego escribir el nombre de la clase principal. Una vez hecho esto, el propio KToolbar nos indicará dónde copiar los fuentes para luego poder compilar y ejecutar el proyecto. El lector encontrará los fuentes en el directorio “Codigo” del CD-ROM. Es necesario entender que ambos procedimientos son equivalentes, y que por lo tanto el código del directorio “Codigo” también se encuentra incluido en los proyectos del directorio “Proyectos” (dentro del directorio “src” correspondiente).
Conclusiones Con este artículo ya hemos completado los conocimientos técnicos necesarios para estar en disposición de crear un juego que supere las limitaciones de los terminales MIDP 1.0. En este artículo hemos visto cómo los fabricantes de juegos Java, hasta la aparición de los presentes terminales MIDP 2.0, todavía no demasiado extendidos entre los potenciales usuarios de nuestros juegos, tienen que recurrir a APIs adicionales que son soportadas con diferentes matices según el terminal. Se aprecia por tanto la gran dificultad que entraña el desarrollo de juegos realmente multiplataforma, sin tener que recurrir a distintas compilaciones de un mismo código fuente adaptado a cada teléfono. En este sentido existen iniciativas muy interesantes como es el proyecto J2ME Polish que se puede conocer en la dirección http://www.j2me http://www.j2mepolish.org/. polish.org/. En el próximo artículo nos pondremos manos a la obra y configuraremos el IDE gratuito Eclipse (http://www.eclipse.org/) para facilitarnos la labor de programar en J2ME no estándar, para lo cuál también instalaremos y configuraremos algunas herramientas gratuitas de Nokia.
Agradecimientos Se quiere agradecer a la empresa Flag Solutions (http://www.flagsolutions.net) y al grupo AWEG (Adaptive Web Engineering Group) de la Universidad de Salamanca sus aportaciones y consejos para la elaboración de este artículo.
Referencias [1] [2]
SUN MICROSY MICROSYSTEMS STEMS JSR-37 (15 Diciem Diciembre bre 2000). 2000). MIDP (Mobi (Mobile le Informa Information tion Device Profil Profile) e) http:// http://java.su java.sun.com/ n.com/produ products/mi cts/midp/in dp/index.j dex.jsp. sp. W3C. Portable Portable Network Graphi Graphics cs (PNG) (PNG) Specificat Specification ion (Second (Second Editio Edition). n). Informati Information on technol technology ogy — Compu Computer ter graphics graphics and image image process processing ing — Po Portable rtable Network Graphics (PNG): Functional specification. ISO/IEC 15948:2003 (E). W3C Recommendation 10 November 2003. http://www.w3.org/TR/PNG/.
http://digital.revistasprofesionales.com
27
SOLO PROGRAMADORES nº 124
MIDDLEWARE
Programación distribuida en .NET (II) DIEGO LZ. DE IPIÑA GZ. DE ARTAZA ARTAZA (Profesor (Profesor del departamento de Ingeniería del Software de la facultad de Ingeniería de la Universidad de Deusto Deusto (ESIDE)).
Tras conocer en la primera entrega las piedras angulares de la programación distribuida a bajo nivel: sockets, multithreading y XML, ahora analizamos .NET Remoting, la tecnología por excelencia para el desarrollo de aplicaciones distribuidas en .NET. Introducción
Remoting consiste en un conjunto de servicios y canales de comunicación que transmiten mensajes entre aplicaciones remotas, con la ayuda de formateadores que codifican y decodifican esos mensajes. A continuación estudiamos en detalle esta poderosa herramienta de programación distribuida.
.NET Remoting básico En .NET, una clase es remota cuando puede ser usada por clientes en otro dominio de aplicación, es decir, en el mismo proceso, en otro proceso o en otras máquinas. Para construir una clase remota hay que seguir los siguientes pasos: 1. Derivar la clase de “System.MarshalBy RefObject”. Por ejemplo: public class ClaseRemota: MarshalBy
Gracias a .NET Remoting los objetos de nuestra aplicación podrán residir en máquinas remotas SOLO PROGRAMADORES nº 124
28
ASP.NET es una herramienta adecuada para la construcción de clientes ligeros que sólo visualizan lenguaje de marcado a través de un navegador. Sin embargo, 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 desarrollo de este tipo de aplicaciones. .NET Remoting sustituye a la tecnología DCOM para crear aplicaciones distribuidas sobre plataformas Windows. Proporciona una arquitectura orientada a objetos que como todo buen middleware otorga transparencia de localización a los componentes distribuidos. En Remoting, los componentes de una aplicación pueden concentrarse en un único ordenador o en múltiples nodos alrededor de Internet, sin que el consumidor de tales servicios sepa que dichos componentes están distribuidos. Remoting permite invocar métodos y pasar objetos más allá de los dominios de nuestra aplicación de una manera sencilla, flexible y muy configurable. Combina estándares ya existentes como: SOAP (Simple Object Access Protocol), para codificación de mensajes, o HTTP y TCP, como protocolos de comunicación, con formateadores binarios propietarios destinados a conseguir un alto rendimiento en las comunicaciones. Básicamente, .NET
RefObject { ... }
2.
Cuando un cliente cree una instancia de “ClaseRemota”, realmente se creará un proxy de la misma. Un proxy es un objeto que “pretende” ser otro. Es decir, llamadas recibidas por el proxy son transmitidas al objeto remoto a través de un canal que conecta los dos dominios de aplicación. Realmente el cliente sólo mantiene una referencia al objeto, no una copia del mismo. El cliente interactúa con un objeto local, el proxy, que encapsula las complejidades de la comunicación distribuida con un objeto remoto. Registrar la clase para que pueda ser activada desde otro dominio de aplicación. Una clase remota se puede registrar a través de dos métodos estáticos definidos en “System.Runtime.Remoting. RemotingConfiguration”: “RegisterActivated ServiceType” y “RegisterWellKnownServiceType”. Asimismo, en .NET Remoting se pueden definir dos tipos de objetos remotos: (1) server-activated y (2) client-activated.
Objetos activados en la parte cliente o en la parte servidora Los objetos activados en la parte servidora (serveractivated) tienen las siguientes propiedades: registran con “RegisterWellKnown Se ServiceType” y “RegisterWellKnownClient Type”. http://digital.revistasprofesionales.com
MIDDLEWARE
Programación distribuida en .NET (II)
Cuando el cliente invoca “new” sólo se crea un proxy en la parte cliente, el objeto no se crea en la parte servidora hasta que una invocación es recibida. Sólo se pueden usar constructores por defecto sin parámetros. Por su parte, los objetos activados en la parte cliente (client-activ (client-activated): ated): registran con “RegisterActivated Se ServiceType” y “RegisterActivatedClientType”. El objeto remoto se crea en la parte servidora inmediatamente después de llamar a “new” en el cliente. Se pueden activar con constructores con parámetros. Cuando registras un objeto activado en la parte servidora se pueden especificar dos modos de comportamiento: “WellKnownObjectMode.SingleCall”, se crea una nueva instancia de la clase remota por cada invocación recibida de un cliente. se “WellKnownObjectMode.Singleton”, crea una instancia de la clase remota para procesar todas las llamadas de los clientes. Los objetos activados en la parte del cliente ofrecen sólo un modo de activación. Cada llamada a “new” por un cliente creará una instancia en el servidor que preserva estado de una llamada a otra. Si se desea mantener estado por cada cliente, este modo de activación es idóneo para ello. A modo de ejemplo, el siguiente fragmento de código activa un objeto de tipo “ClaseRemota” en la parte servidora, bajo la URI “ClaseRemota”, con un comportamiento “SingleCall”, es decir, se creará una instancia del 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 Remoting Para hacer que una clase remota sea accesible por clientes, el proceso servidor tiene que crear y registrar un canal (channel). Un canal es un conducto para transportar los mensajes desde y hacia los objetos remotos. La misión de un canal es tomar datos, crear un paquete según las especificaciones de un protocolo y enviar el paquete a otro ordenador. Cuando un cliente invoca remotamente un método, los parámetros y otros detalles referidos a la invocación http://digital.revistasprofesionales.com
son transportados a los objetos por medio del canal. De la misma forma son transportadas las respuestas a esa invocación. Hay dos tipos de canales predefinidos en .NET: Canales TCP (“TcpServerChannel” y “TcpClient Channel”) usan TCP para comunicarse y transmiten datos, por defecto, en formato binario. Son adecuados cuando el rendimiento es lo importante, ya que los datos se transmiten por medio del formato de serialización binario diseñado para .NET Remoting. HTTP (“HttpServerChannel” y Canales “HttpClientChannel”) usan HTTP para comunicarse. Lo más normal es que transporten mensajes de tipo SOAP. Son adecuados cuando lo que prima es la interoperabilidad. El canal HTTP es comúnmente utilizautilizado para las comunicaciones en Internet. Una interesante propiedad de los objetos que usan estos canales es que permiten el uso de IIS como su agente de activación. El siguiente fragmento ilustra cómo crear un canal TCP en la parte servidora escuchando en el puerto 1234: TcpServerChannel channel = new Tcp ServerChannel(1234); ChannelServices.RegisterChannel(channel);
Por su parte, una aplicación cliente que quiera crear una instancia de una clase remota también tiene que registrarse. Para que un cliente pueda hablar con la parte servidora de una clase remota, escuchando en un “TcpServer Channel”, debería crear un “TcpClientChannel”. Si el cliente quiere usar “new” para instanciar un objeto remoto, debe registrar la clase remota en el dominio de aplicación local. “RegisterWellKnownClientType” registra una clase en el cliente correspondiente a una clase “RemotingConfiguration.RegisterWellKnown ServiceType” en el servidor. El siguiente código muestra 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 efectuado sus registros correspondientes se crea la instancia de “ClaseRemo “ClaseRemota”: ta”:
ClaseRemota cr = new ClaseRemota();
La infraestructura .NET Remoting es altamente configurable y extensible. Es perfectamente posible definir nuevos canales y formateadores a través de .NET Remoting que permitan comunicarse con servicios/objetos distribuidos desarrollados con otras populares herramientas de programación distribuida, como CORBA, RMI o Tibco RV. Un buen ejemplo de ello ha sido la integración del protocolo IIOP de CORBA en .NET con la extensión Remoting.CORBA, incluida en el CD-ROM y disponible en http://remotingcorba.sourceforge.net. Gran parte de la capacidad de interoperabilidad de .NET Remoting es debida a que integra SOAP. Aunque no es el protocolo más eficiente, permite gran flexibilidad. SOAP es un protocolo basado en XML que especifica un mecanismo mediante el cual aplicaciones distribuidas pueden intercambiar información independientemente de la plataforma. Aunque, normalmente, SOAP es usado junto con HTTP para su transporte, SOAP puede utilizar cualquier protocolo de transporte (por ejemplo SMTP). Para más detalles visitar http://www.w3.org/TR/SOAP/.
Interoperabilidad vs. rendimiento en .NET Remoting La figura 1 muestra las posibilidades de explotación ofrecidas por .NET Remoting. En la parte servidora podemos tener servidores configurados con un canal TCP que son utilizados por clientes locales dentro de una LAN. En ese caso, para la transmisión de datos se usa el mecanismo más eficiente, transmisión en binario. Por otro lado, en la parte servidora podemos tener un servidor con un canal HTTP que ha sido activado por IIS. La información transmitida entre este servidor y sus potenciales clientes se realiza por medio del estándar SOAP. Obsérvese que esta configuración IIS + canal HTTP/SOAP es ideal para situaciones donde deseamos alojar un servicio detrás de un cortafuegos que sólo tolera conexiones remotas vía HTTP en el puerto 80. Al utilizar SOAP los clientes no tienen porque necesariamente haberse programado en .NET Remoting. Clientes web estándar desarrollados bien con .NET u otros lenguajes como Java o Python podrían utilizarse. Consecuentemente, si queremos interoperabilidad adoptaremos una solución basada en canales HTTP y SOAP. Si queremos máximo rendimiento utilizaremos TCP y formateo binario. La primera opción será ideal cuando queremos que nuestro servicio sea consumido por clientes externos y se encuentre protegido
29
SOLO PROGRAMADORES nº 124
MIDDLEWARE
a este problema es el registro declarativo en .NET. Este mecanismo toma información de un fichero que es procesado al invocar al método estático “RemoteConfiguration.Configure”. Modificar el cliente para consumir el objeto “Reloj” alojado ahora en otra máquina sería tan sencillo como editar su fichero de configuración asociado “ClienteReloj.exe.config”.
Transfiriendo objetos como argumentos en .NET Remoting A veces es necesario pasar a un método como parámetro de entrada o salida un objeto. Cuando el objeto es pasado por valor, el marco de Remoting se encarga de hacer una copia completa del objeto para que pueda ser enviado a través de un canal. En el framework .NET existen dos formateadores de serialización que se encargan de codificar y decodificar los mensa jes: je s: .NET .NET bina binari rioo (“Sy (“Syst stem em.R .Run unti time me.S .Ser eria ialiliza zati tion on.. Formatters.Binary”) y SOAP (“System.Runtime. Serialization.Formatters.SOAP”). Si un objeto tiene una gran cantidad de información (el contenido de una tabla de una BBDD), será adecuado pasarlo por referencia, y luego utilizar la referencia recibida en el cliente para ir progresivamente, según demanda, recuperando el contenido del mismo.
Figura 1. Arquitectura de .NET Remoting. Remoting.
tras un cortafuegos. La segunda será adecuada para el desarrollo de aplicaciones distribuidas eficientes a utilizar dentro de una LAN.
Nuestra primera aplicación con .NET Remoting Apliquemos los conceptos aprendidos hasta el momento desarrollando un sencillo servicio distribuido que devuelve la hora actual en .NET Remoting. En primer lugar, creamos una clase que hereda de “System.MarshalByRefObject” (véase el listado 1). A continuación, creamos la clase “Servidor Reloj” que usa un canal TCP para recibir peticiones dirigidas al objeto remoto “Reloj” activado en el servidor con modo de comportamiento “SingleCall” (véase el listado 2). Finalmente, creamos la clase “ClienteReloj” que simplemente se conecta a través de un canal TCP con el objeto remoto “Reloj” e invoca su método “ObtenerHoraActual” (véase el listado 3). La figura 2 muestra esta aplicación en ejecución.
Configuración declarativa Las clases “ServidorReloj” y “ClienteReloj” usan información de configuración embebida en el
SOLO PROGRAMADORES nº 124
30
código para registrar canales y clases remotas. En consecuencia, si deseamos cambiar la dirección IP o el puerto en el que escucha un servicio debemos recompilar el código. La solución
Creación de proxies Para generar un proxy de un objeto remoto no es siempre necesario ni conveniente utilizar
LISTADO 1
Reloj.cs
// compilar: csc /t:library Reloj.cs using System; public class Reloj: MarshalByRefObject { public string ObtenerHoraActual() { return DateTime.Now.ToLongTimeString(); } }
LISTADO 2
ServidorReloj.cs
// compilar: csc /r:Reloj.dll ServidorReloj.cs using 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(); } }
http://digital.revistasprofesionales.com
MIDDLEWARE
Programación distribuida en .NET (II)
ConversorRomanoArabe con canal TCP En el fichero “IConversorRoma “IConversorRomanoArabe.cs” noArabe.cs” (adjunto en el CD-ROM) hemos colocado las clases “ConversorRomanoArabeConstants” “ConversorRom anoArabeConstants” y “Usuario”, y la interfaz “IConversorRomanoArabe”. La clase “ConversorRomanoArabeConstants” declara todas las constantes utilizadas para el desarrollo de este servicio. Por ejemplo la enumeración “NumeroRomanoEnum” es un mapa de valores en romano a decimales (árabes):
Figura 2. Ejecución de la aplicación aplicación distribuida Reloj.
LISTADO 3
ClienteReloj.cs
// csc /r:Reloj.dll ClienteReloj.cs using 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()); } }
“new”. El uso de “new” obliga al cliente a tener acceso a la implementación del objeto remoto (su dll o exe) para generar su proxy. La clase “System.Activator” ofrece un par de métodos estáticos que nos permiten instanciar proxies de objetos remotos simplemente teniendo acceso a su interfaz: “GetObject” se usa para activar objetos en la parte servidora. “CreateInstance”” se usa para activar obje “CreateInstance tos en la parte cliente. Si utilizamos cualquiera de los métodos en “System.Activator” ya no será necesario usar “RegisterActivatedClientType” o “Register WellKnownClientType”. Por ejemplo, hasta ahora hemos visto que para crear una instancia 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 http://digital.revistasprofesionales.com
remoto sin poseer otro conocimiento que su URL 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 ConversorRoma Transformando ConversorRomanoArabe noArabe a .NET Remoting Vamos a utilizar ahora los conceptos mostrados sobre .NET Remoting para transformar la aplicación de conversión de números romanos a árabes (vista en la entrega anterior), y viceversa, a una aplicación en .NET Remoting. Los pasos que seguiremos serán: 1. Transformación del conversor a un servidor .NET Remoting con canal TCP, configurado de manera programática. 2. Transformación del conversor a un servidor .NET Remoting con canales TCP y HTTP, configurado declarativamente. 3. Activación del servidor de conversión mediante IIS.
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 de logeo de un usuario que desea utilizar el servicio “ConversorRomanoArabe”. El listado 4 muestra su código. En el listado 5 se muestra la interfaz que define el contrato ofrecido por el servicio de conversión. Todo cliente (“ConversorRomanoArabeClient”) deberá ajustarse a ese contrato para poder comunicarse con el objeto remoto que implementa tal interfaz (“ConversorRomanoArabe”). A diferencia de nuestra anterior implementación del servicio mediante sockets (esta implementació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és de acabar de consumir el servicio, respectivamente. “Login” devuelve un token de autenticación que será enviado junto con cada petición de conversión. De esa manera, evitaremos que usuarios no autorizados tengan acceso a nuestro “valioso” servicio distribuido. La implementación del servicio “Conversor RomanoArabe” en .NET Remoting se muestra en el listado 6. Esta clase remota hereda como siempre de “MarshalByRefObject” e implementa la interfaz “IConversorRomanoArabe”. El constructor de esta clase simplemente inicializa una tabla que mapea nombres de usuario a contraseñas (usuarios) y una lista con los tokens asignados a clientes autorizados. El método “Login” simplemente verifica que el nombre de usuario y contraseña pasados existen en la tabla usuarios, y en caso afirmativo genera un token de autorización para el cliente. Este token deberá ser utilizado por dicho cliente cada vez que requiera una conversión, es decir, use el servicio “ConversorRomanoArabe”. El listado 7 muestra cómo antes de efectuarse la conversión se verifica que el token pasado como argumento es válido.
31
SOLO PROGRAMADORES nº 124
MIDDLEWARE
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; } }
Figura 3. Cliente del servicio ConversorRomanoArabe ConversorRo manoArabe programado con .NET Remoting.
ArabeServer” tan sólo tendremos que colocar la siguiente sentencia para configurar el canal y modos de activación de este servicio: RemotingConfiguration.Configure (“ConversorRomanoArabeServer.exe.
public string Contraseña { get { return this.contraseña; } set { this.contraseña = value; } }
config”);
}
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); }
El listado 8 muestra cómo de manera programática se configura el tipo de canal, puerto y modo de comportamiento del servicio “ConversorRomanoArabe”. En este caso utilizamos un canal de tipo TCP y activamos el objeto en el servidor tras recibir una invocación del cliente. Todos los clientes comparten la misma instancia del servidor, ya que el modo de comportamiento del objeto es Singleton. Finalmente, en el listado 9 mostramos el código de un cliente que utiliza el servicio “ConversorRomanoArabe”. La figura 3 muestra un cliente de .NET Remoting utilizando el servicio “ConversorRomanoArabe”.
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; } } // ...
ConversorRomanoArabe con canal ConversorRomanoArabe HTTP declarativo Analicemos ahora cómo modificar el conversor para que de manera declarativa, tan sólo modificando un par de ficheros de configuración y sin recompilar, consigamos modificar el tipo de canal o puerto utilizado por “Conversor RomanoArabe”. En la clase “ConversorRomano
Esta sentencia simplemente indica que el fichero “ConversorRomanoArabeServer.exe.config” (véase el listado 10) contiene la configuración del servidor. Obsérvese que ahora este servidor es accesible a través de tanto un canal TCP en el puerto 1234 como un canal HTTP en el puerto 8080. Por otra parte, las modificaciones necesarias para permitir la programació programación n declarativa del cliente serían:
} }
http://digital.revistasprofesionales.com
MIDDLEWARE
Programación distribuida en .NET (II)
Modificación del método ArabeARomano de ConversorRomanoArabe
LISTADO 7
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 Conversor ConversorRomanoA RomanoArabeServer rabeServer
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(); } } WellKnownClientTypeEntry[] serviceMetadata = RemotingConfiguration.
con IIS es aún mejor, dado que podemos hacer que nuestro servidor transparentemente escu-
che a través del puerto 80 normalmente abierto 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ón sobre “Sitios Web por Defecto” y seleccionaremos “Nuevo” -> “Directorio Virtual”. Introduciremos el nombre “Conversor RomanoArabe” y lo asociaremos a un directorio de nuestro disco duro en el que hemos colocado el código fuente de la aplicación (como siempre, disponible en el CD-ROM). A continuación crearemos un fichero “web.config” en ese directorio con el contenido mostrado en el listado 12. La figura 4 ilustra la configuración del directorio virtual con inetmgr. El código para el servicio “Conversor RomanoArabe” será el mismo que hasta ahora. La única salvedad es que ahora no necesitaremos definir la clase “Conversor RomanoArabeServer”, ya que la activación del servicio la realizará IIS. Por otro lado, el código del cliente tampoco cambiará, tan sólo el fichero de configuración “ConversorRomanoArabeClient.exe.config” requerirá una mínima modificación para utilizar la nueva URI del objeto remoto ahora acti-
(IConversorRomanoArabe)Activator.Get Object(typeof(IConversorRomanoArabe), serviceMetadata[0].ObjectUrl); // ... código que usa el conversor
De nuevo, se hace uso de un fichero de configuración (véase el listado 11) para determinar los parámetros de conexión al componente servidor. En este caso se elige utilizar el canal HTTP. Recordar que a través de la programación declarativa podremos cambiar la ubicación (dirección IP) y número de puerto del servidor sin necesidad de recompilar el código del servidor o los clientes.
ConversorRomanoArabe activado ConversorRomanoArabe por IIS Como última mejora de nuestro conversor vamos a hacer que el servidor web IIS lo active en demanda al recibir conexiones de clientes. De esta manera nos evitamos la tediosa tarea de tener que manualmente arrancar el servidor, y de tenerlo que mantener en ejecución incluso cuando nadie lo está utilizando. Una alternativa a la activación vía IIS podría haber sido la creación de un servicio Windows con este servidor .NET Remoting. No obstante, la activación http://digital.revistasprofesionales.com
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 10
Fichero de configuración ConversorRomanoArabeServer.exe.config
33
SOLO PROGRAMADORES nº 124
MIDDLEWARE
LISTADO 11
Figura 4. Directorio virtual virtual ConversorRomanoArabe ConversorRo manoArabe en IIS.
vado por IIS en el puerto 80 y bajo el contexto “ConversorRomanoArabeServer”. A continuación mostramos la única modificación con respecto a la anterior versión del fichero:
Algo importante a reseñar es que deberemos colocar la dll con el código del objeto remoto en el subdirectorio “bin” del directorio donde está colocado el “web.config”, ya que es donde lo busca IIS. Es decir, asumiendo que los ficheros .cs están en el mismo directorio que el “web.config”, compilaremos los ficheros “IConversorRomanoArabe.cs” y “ConversorRomanoArabeServer.cs” del siguiente modo: csc /t:library /out:bin\IConversor RomanoArabe.dll IConversorRomanoArabe.cs
Fichero de configuración ConversorRomanoArabeCl ConversorR omanoArabeClient.exe.config ient.exe.config
LISTADO 12
Fichero web.config para el Directorio Virtual ConversorRomanoArabe
Para más detalles sobre cómo compilar y ejecutar todos los ejemplos de esta entrega consú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ísticas principales del framework para programación distribuida orientada a objetos .NET
Remoting: modos de activación, modos de comportamiento, canales de comunicación, y transferencia de objetos como parámetros. parámetros . Para demostrar estos conceptos hemos transformado el ConversorRomanoArabe de la anterior entrega a un servicio distribuido programado en .NET Remoting. En la siguiente entrega, describiremos otras características más avanzadas de .NET Remoting como leasing o creación de servicios web con .NET Remoting. Además, revisaremos .NET Enterprise Services, la solución en .NET para el desarrollo de aplicaciones distribuidas de alto rendimiento y elevada disponibilidad, análoga a J2EE en Java.
2.0 en Visual Studio 2005 Una de las novedades más interesantes de la nueva versión de es la incorporación de las páginas maestras. En la próxima entrega del coleccionable descubriremos descubrir emos cómo las páginas maestras pueden abreviar el ciclo de desarrollo de una aplicación web, todo ello desde el nuevo entorno Visual Studio 2005. Patrocinado por: Autor: Francisco Charte
MIDDLEWARE
XAML (IV) ERICH R. BÜHLER (MVP en .NET Framework) Framework)
El acceso a orígenes de datos es una característica deseable para cualquier aplicación. Esto nos conduce a un problema, no siempre bien resuelto: ¿Cómo mostrar estos datos al usuario? La solución que ofrece XAML es elegante elegante y seguro seguro que muchos quedarán sorprendidos después de practicar con ella. Introducción En los artículos anteriores aprendimos a emplear los controles nativos de XAML para conformar una interfaz gráfica y vimos cómo modificar su apariencia. Básicamente esta tarea se lleva adelante mediante estilos visuales, los que hacen posible personalizar la conformación total o parcial de un control, tanto sea para definir uno nuevo o para alterar alguna faceta del mismo. Todo esto gracias al fabuloso lenguaje de marcación XAML que será incluido en la próxima versión del sistema operativo de Microsoft, aunque el lector puede ya hacer uso de esta tecnología descargando e instalando Avalon Community Technology Preview del sitio MSDN. Esto hará que pueda prescindir de complejas líneas de código de programación para finalmente remitirse a etiquetas para crear una interfaz de usuario; ya puede crear su anhelado botón redondo o la lista con elementos de imágenes con hipervínculos. Ahora bien, será necesario conocer cómo anidar cada uno de los miembros para así obtener un resultado consistente. En este penúltimo artículo del curso sobre programación de interfaces con XAML iré más allá y explicaré cómo enlazar XAML a datos para finalmente desembocar en una de las características que a mi parecer es de las más destacables y poderosas, llamada “Estilo de Datos”. También mostraremos cómo crear aplicaciones ejecutables de Avalon para comenzar a cerrar SOLO PROGRAMADORES nº 124
36
el círculo de tecnologías y herramientas. Sin embargo, antes vamos a hablar sobre las capacidades de este nuevo estándar para la conexión a datos, algo que hemos dejado hasta el momento para ofrecer primero una buena base en los temas básicos de XAML.
El enlace a datos Cuando se piensa en el enlace a datos, todos imaginamos una aplicación que obtiene información de alguna parte y posteriormente la exhibe. Por supuesto que esto involucra mucho más que este simple punto de vista, ya que por debajo existen traslados de paquetes de bytes desde el origen hasta la interfaz gráfica, manejadores de base de datos, transformaciones, redes, etc. Afortunadamente, pocos de estos procesos nos interesan ya que en XAML esta tarea se resuelve de forma sencilla, aunque no por ello deje de ser poderosa y flexible. Además de la complejidad de actores que mencioné anteriormente los datos pueden ser de tipos variados; cuando digo esto no me refiero a que el origen sea un motor SQL Server u Oracle, sino a formatos realmente dispares, como podría ser un documento XML, el valor de una propiedad de un objeto o una base de datos. También se cuentan con varias alternativas de cómo manipular la información, se puede indicar que los datos vendrán del origen a la interfaz gráfica pero nunca volverán a éste o incluso ser bidireccional. Los eventos juegan necesariamente un papel importante ya que hacen posible recibir notificaciones de cuándo la conexión está abierta, que ha llegado la información, así como también modificar la misma para que sea representada de una forma diferente a la original (transformaciones). Todo esto que he mencionado parece muy complejo en términos generales, pero el lector comprobará en las próximas páginas que no lo es tanto. La clase Bind
La nueva infraestructura provee una clase llamada “Bind” la cual es vista dentro del lenguahttp://digital.revistasprofesionales.com
MIDDLEWARE
XAML (IV)
Algunas de las clases del espacio System.Windows.Data je declarativo decl arativo XAML X AML como una u na etiqueta etiqu eta de igual nombre. Esta es la responsable de vincular un elemento con datos, por lo que interactuar con sus propiedades hará posible un control total sobre el enlace. Todas las clases relacionadas con consumo de información se encuentran dentro del espacio “System.Windows.Data”. El cuadro “Algunas de las clases del espacio System.Windows.Data” nos muestra un pequeño resumen de ellas, ya que su totalidad abarca más de 30 estructuras, aunque en realidad solamente se emplean 2 o 3 a no ser que desee realizar alguna implementación con características realmente avanzadas. Como podemos apreciar se tienen 3 posibles modelos de conexión y consumo de datos, uno orientado al típico modelo relacional, otro a un documento XML, y el último que hace posible enlazarse con propiedades de objetos, cosa que es de mucha utilidad cuando se está trabajando en .NET Framework. El siguiente código contiene un pequeño ejemplo de cómo indicar un campo a consumir:
Más adelante nos centraremos en la forma de establecer el origen de datos. Como puede apreciarse en el código anterior, se declara una etiqueta de imagen y posteriormente se anida una segunda de tipo “Bind”. Ésta utiliza la propiedad “DataSource” que indica el nombre del origen de datos. Por su parte “Path” apunta al elemento deseado (del que nos interesa su valor) que es llamado “Imagen”. Básicamente esto obtendrá el contenido del miembro y lo pondrá en el control, exhibiéndose finalmente dentro del mismo. Por supuesto que existen muchas alternativas a la hora de vincular un control a datos, pero por una cuestión de espacio solamente me remitiré a ver aquellas opciones que nos serán de utilidad para explicar más adelante las características de “Estilo de Datos”. Como se mencionó anteriormente hay varios tipos de origen, como por ejemplo un documento XML. En este formato la información viene organizada de forma jerárquic jerá rquica, a, lo que hace que en algun algunas as http://digital.revistasprofesionales.com
Clase
Descripción
Define un objeto que contendrá la declaración de enlace entre un elemento de la interfaz gráfica y un origen de datos. Representa un enlace con datos. Se puede enlazar con propiedades de ObjectDataSource otros objetos como origen/destino de datos. SqlDat Sql DataSo aSourc urcee Pro Proveed veedor or específi específico co para para enlazar enlazar con Micro Microsof softt SQL Server Server. se desea consumir información en formato XML, es ésta la opción XmlDataSource Si que se deberá emplear (lo veremos aquí más adelante). Bind
Propiedades de Bind Propiedad
Descripción
TwoWays: Modifica la interfaz o el origen si alguno de ellos cambia. BindType 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 la interfaz gráfica o al ser llevados al origen de datos. IsAsync IsAs ync Indica Ind ica cuá cuándo ndo los valo valores res se deber deberán án obt obtener ener/esc /escribi ribirr en for forma ma asín asíncro crona. na. ValidationR Valid ationRules ules Es de tipo colección y permite establecer reglas de validación a aplicar en el momento de enviar los datos. ocasiones sea necesario indicar una ruta que apunte al nodo específico dentro de la jerarquía. Esto no es un problema con “Bind” ya que ofrece el miembro “XPath” que permite definir el criterio de selección. El siguiente fragmento de código nos muestra cómo indicar un nodo inmediato de la jerarquía utilizando esta propiedad, aunque esto podría ser una ruta como por ejemplo la senda de un directorio de MSDOS (“/Imagen/VersionBlancoy Negro”):
DataSource=”{DatosLibros}”
XPath=”Imagen”/>
Existe también una forma más económica desde el punto de vista de la escritura, el atajo en cuestión hace lo mismo desde el punto de vista funcional pero usando una sola línea. Sé que a algunos programadores les gusta tener todo compacto en vez de emplear propiedades complejas (etiquetas anidadas). En general yo evito esta opción ya que mi criterio le quita legibilidad al código, pero no obstante es bueno que el lector lo conozca. Para utilizar esta sintaxis habrá que asignar directamente en la propiedad donde se desea mostrar el resultado un asterisco seguido de la palabra “Bind” y luego entre paréntesis todos los valores para el enlace separados por punto y coma. La siguiente línea nos muestra cómo hacerlo:
Hemos visto cómo vincular un enlace con un control simple aunque también es posible hacer lo mismo con una lista de elementos (“Listbox”). Ello brinda la posibilidad de exhibir varios miembros en vez de uno solo. Para esto es necesario bajar por la jerarquía de “Listbox” hasta toparnos con la colección de elementos de la lista y allí establecer el enlace. Veamos cómo se hace esto en el siguiente fragmento de código:
Antes de pasar a detallar todo lo relacionado con la conformación de la conexión, veamos en el cuadro “Propiedades de Bind” algunas de las propiedades que ofrece “Bind” para personalizar la forma en que los datos serán tratados. Estableciendo el origen de datos
Como ya se ha dicho, todas las clases relacionadas con un enlace a datos se 37
SOLO PROGRAMADORES nº 124
MIDDLEWARE
LISTADO 1
encuentran dentro del espacio “System. Windows.Data”. El cuadro “Algunas de las clases del espacio System.Windows.Data” nos mostró un pequeño resumen de los miembros allí contenidas ya que su totalidad abarca más de 30 estructuras. Básicamente se proveen 3 tipos diferentes de enlace, uno que es el tradicional (“SqlDataSource”), para vincular estructuras XML (“XmlDataSource”), y lo más interesante… para consumir un objeto creado por nosotros mismos (“ObjectData Source”). Comencemos por lo básico, el listado 1 nos muestra un documento XML con información sobre libros. Por una cuestión de comodidad esta información la incluiré dentro del mismo documento XAML que define la interfaz gráfica, sobre todo para no tener que hacer referencia a archivos externos. A esto se le llama “isla de datos” ya que los mismos se encuentran dentro de un único documento. Debido que el formato es XML se tendrá que emplear la estructura “XMLDataSource” (véase el listado 2).
Nuestra lista de libros
Guía de migración y actualización a Visual Basic .NETGuia.jpgCocinando con .NET framework y XAML en 5 minutosCocinando.jpgCenando con .NET framework y con otras tecnologíasCenando.jpgWoman .NET una historia de amor en el ciberframeworkMujer.jpg
LISTADO 2
Accediendo a nuestra lista de libros
n”> Guía de migración y actualización a Visual Basic .NETGuia.jpg ...
“XPath” indica el nodo en el documento por el que se desea filtrar así como el nombre que se empleará e mpleará para la conexión. Con esto basta para que el enlace esté completo. Por supuesto que el documento que alimenta al origen puede estar en un archivo independiente. Para ello solamente hay que indicar en el origen (“Source”) el nombre del archivo:
Como ve la diferencia en sintaxis es muy pequeña, pero nos permite utilizar un archivo independiente en vez de la “isla XML”.
Estilo de Datos
Figura 1. La tecnología “Estilo “Estilo de Datos” permite definir la forma en la que quer emos presentar los datos obtenidos del origen. SOLO PROGRAMADORES nº 124
38
Cuando exhibimos datos por ejemplo dentro de un control de lista, en realidad estamos acostumbrados a que sean mostrados como elementos de texto uno debajo del otro. Esto no está mal, aunque parece que esto ha resultado un poco aburrido al grupo de arquitectos de XAML, por lo que han dado un paso más allá a esta aproximación. Ahora cuando se enlazan los datos a un elemento de la http://digital.revistasprofesionales.com
MIDDLEWARE
XAML (IV)
LISTADO 3
Definición del estilo MiEstilo
Esto nos asegura que la nueva definición visual será utilizada por los elementos contenidos así se carguen de un origen o utilizando las primitivas del control de lista. El tercer y último paso consiste en indicar cómo localizar el origen de datos, para ello simplemente se deberá adicionar dentro de la colección de elementos la etiqueta “Bind” indicando el nombre de la conexión mediante “DataSource”:
interfaz gráfica es posible indicar una plantilla de visualización específica. Por ejemplo, el primer campo a ser mostrado en la “ListBox” lo podríamos plasmar como un texto, pero el segundo al ser una imagen emplearíamos un control “Picture”, mientras que el tercero lo mostraríamos como hipervínculo. Para cubrir esta necesidad se cuenta con una nueva tecnología que hace posible definir una plantilla que transformará los datos de origen a un tipo de visualización específico. Como puede ver la tecnología de “Estilo de Datos” es una mezcla entre características avanzadas de presentación e información. La figura 1 muestra un control de “ListBox” que he modificado para que su apariencia sea adecuada a los datos suministrados por el origen. Básicamente los pasos a seguir son siempre los siguientes tres: 1. Crear un estilo para los datos (cómo éstos serán mostrados). 2. Asociar el control con el estilo creado previamente. 3. Conectar el control al origen de datos. Estableciendo el estilo
El primer paso entonces es definir un estilo para los datos. En la entrega anterior ya se explicó que todo estilo debe ser definido como un elemento de la colección de recursos. El listado 3 nos muestra una apariencia personalizada llamada “MiEstilo” donde se emplean varios controles para exhibir los diferentes elementos del origen de datos; cada uno de ellos cumple un rol meramente estético. Sin http://digital.revistasprofesionales.com
embargo, hay que prestar atención a las líneas que se encuentran resaltadas. La totalidad de la etiqueta “Bind” será reemplazada por el valor del campo definido en la propiedad XPath. El título será insertado dentro de un contenedor de texto, mientras que con el segundo elemento (“Image”) se hará algo más interesante ya que se utilizará este contenido para alimentar la imagen. Por ejemplo, si se tiene un valor de campo “guia.gif” entonces se irá al directorio actual y se cargará la imagen que tenga este nombre. En caso de no existir no se producirá un error sino que se omitirá la misma. La propiedad “VisualTree” tiene un papel crucial ya que como vimos en el capítulo anterior todo lo que se escriba dentro de ella sobrescribirá la apariencia predeterminada del control. El resto de paneles y etiquetas simplemente sirven para alinear los datos. Hemos culminado el primer paso, ahora tenemos que asociar el control con el estilo creado previamente, con el fin de que se comience a utilizar la nueva forma de plasmar la información. Evidentemente no deseamos que se aplique la apariencia a toda la lista “Listbox” sino a sus eleme ntos miembros (“Items”). Para ello el control cuenta con una propiedad llamada “ItemStyle” donde se debe poner el nombre del estilo previamente definido (en este caso llamado “MiEstilo”). Veamos cómo:
Una vez que hemos hecho esto debemos establecer de dónde obtener los datos. Como mencioné anteriormente este origen será un documento XML, por lo que se tendrá que emplear la estructura “XMLDataSource” y nombrar al nodo de dónde obtener la información.
Generando una aplicación Avalon Cuando se tiene un documento XAML cualquiera, éste puede abrirse y modificarse ya que en realidad se trata de un archivo de texto que sigue ciertas reglas. Sin embargo existe la posibilidad de crear una aplicación Avalon (exe) que cumpla la misma función que el documento y más. Básicamente esta tarea consiste en llevar las etiquetas y propiedades a código .NET y posteriormente compilarlo. Cada etiqueta se transformará en una instancia de una clase, mientras que las propiedades serán convertidas a líneas de código que configuren cada uno de sus valores. No obstante la ventaja más notoria es que para tener código asociado a eventos del documento en alguno de los lenguajes de .NET Framework (lógica detrás de escenas) se deberá utilizar forzosamente esta aproximación. Aquí se tendrán entonces 2 archivos, uno que será el archivo XAML en sí con la definición de la interfaz gráfica y otro con la 39
SOLO PROGRAMADORES nº 124
MIDDLEWARE
LISTADO 4
El archivo de información
Nombre_del_espacio_de_nombres de_nombres Nombre_del_espacio_ Nombre_de_mi_Ensamblado Nombre_de_mi_Ensambl adowinexeReleaseMSBuildFalse8.0.402092.0 {55DF4C82-60B1-401E-9A8D-AF62DCA542AF} .xaml Nombre aplicación>.xaml” /> .xaml” /> Nombre
lógica bajo la nomenclatura .XAML.CS (o VB para el caso de ser Visual Basic .NET). Desde este código será posible interactuar/modificar las características del documento, así como prescindir del primero para crear la interfaz desde cero. Por ejemplo, en vez de emplear la etiqueta “Bind” se podrían escribir las líneas de código necesarias para efectuar el enlace en el momento en que se cargue el documento. La herramienta que lleva adelante la compilación se denomina MSBUILD, la que es en realidad el nuevo sistema de compilación para las aplicaciones .NET y futuras versiones de Visual Studio. Simplemente se deberá invocar a esta aplicación desde la línea de comandos, estando siempre sobre la carpeta con el documento XAML a compilar. Se requieren siempre 2 archivos que le indiquen 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 contener más datos, pero el mínimo requerido debe indicar el documento XAML de inicio que tendrá que mostrarse al abrirse la aplicación:
El archivo con información del proyecto puede resultar un poco más aterrador a primera vista ya que contiene mucha información casi incomprensible para el ojo humano. Sin embargo, verá que la mayor parte de las etiquetas siempre permanecen constantes (vea esto en el listado 4).
Se han destacado los valores que habrá que modificar, el resto podrán dejarse con los tipos propuestos. El valor del espacio de nombres (“DefaultClrName Space”), por ejemplo, lo utilizaremos más adelante cuando queramos escribir código detrás de escenas, por lo que volveremos sobre este atributo. El resto de los miembros son auto-descriptivos, por lo que no requieren de explicación alguna. Sin embargo en el caso de “ProjectGuid” es obligatorio obtener un número identificador único para el proyecto, lo que sería igual al DNI de una persona. Para ello hay que utilizar la aplicación guidgen que se encuentra en la carpeta “\Common7\Tools” dentro de Visual Studio. Ésta creará un nuevo identificad identificador or el que que será único único en el tiempo y en el espacio (véase la figura 2). Una vez completada la tarea tendrá los 2 documentos con información de aplicación mas la/las páginas XAML. Bastará ejecutar MSBUILD dentro de la carpeta para que se genere el ejecutable correspondiente a la interfaz definida en XAML.
Figura 2. Generando un identificador identificador para el proyecto.
SOLO PROGRAMADORES nº 124
40
http://digital.revistasprofesionales.com
MIDDLEWARE
XAML (IV)
LISTADO 5
Modificaciones en el documento XAML
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) {} } }
Asociando código detrás de escenas a un evento Como se mencionó anteriormente es relativamente sencillo escribir código que esté asociado a los diferentes eventos de una página XAML; esto es similar a la aproximación que utiliza ASP.NET. Se tendrán entonces 2 archivos, uno con la definición de la interfaz gráfica mientras que otro será el encargado de contener la lógica. Para llevar esto adelante es necesario modificar el primer elemento de la jerarquía del documento XAML para indicarle a MSBUILD dónde localizar la lógica (vea esto en el listado 5). Mientras que el atributo “def:Class” indica el espacio de nombres del ensamblado (véase “DefaultClrNameSpace” en el archivo de
proyecto) y de la clase a la que deberá pertenecer el archivo de código, “def: CodeBehind” especifica el nombre y dónde localizar al mismo. Por su parte es recomendable adicionar a todos los controles un nombre mediante el atributo “ID”, con el fin de que luego se pueda hacer referencia a ellos desde código. También debe asignarse a los nombres de los eventos a capturar cuál será el procedimiento que contendrá su implementación. El código del listado 6 muestra un esqueleto clásico de lógica. Como se puede apreciar se indica el nombre del ensamblado así como también de la clase, la cual en este caso hereda las características del panel “DockPanel” “DockPanel”.. Este procedimiento se “enganchará” automáticamente con la ejecución del clic del botón.
¿Qué hay que tener para ejecutar XAML? En el futuro nuestras interfaces XAML estarán automáticamente soportadas por el nuevo subsistema gráfico Avalon de Longhorn, la próxima versión del sistema operativo de Microsoft (véanse los artículos dedicados a Longhorn en los números 122 y 123 de Sólo Programadores ).). Sin embargo, mientras tanto es posible compilar y ejecutar nuestras interfaces XAML con soluciones alternativas, como las que siguen: Visor XAML de XAMLON y también conversor de Flash a este formato. Es posible descargar la aplicación desde http:// www.xamlon.com. Visor de XAML de Mobiform, que por el momento es la única aplicación con soporte a la librería gráfica Avalon y además con un editor gráfico incorporado. Puede descargarse desde http:// www.mobiform.com. Visor XAML de Microsoft, contenido dentro del paquete Public November 2004 “Avalon” Community Technology Preview, disponible para descarga desde el site de Microsoft para desarrolladores.
Conclusiones
Figura 3. Ejecutando MSBUILD dentro dentro de la carpeta transformaremos el documento XAML en un ensamblado EXE de .NET Framework.
http://digital.revistasprofesionales.com
Y hasta aquí hemos llegado en esta cuarta entrega, en el próximo y último capítulo de la serie hablaremos de cómo animar una interfaz gráfica, cosa muy sencilla pero a la vez muy impactante, así como alguna de las características 3D de XAML. 41
SOLO PROGRAMADORES nº 124
REDES
Sistemas de mensajería con Java Message Service (I) EDUARDO MILLÁN MARTÍNEZ
Artículo public Artículo publicado ado en colaboración con javaHisp java Hispano ano
La especificación de mensajería JMS nos permite construir sistemas de mensajería asíncronos con un alto grado de robustez y sencillez. Además, hoy en día existen en el mercado soluciones JMS de código abierto que proporcionan un grado de madurez suficiente como para ser utilizados en aplicaciones corporativas.
Introducción Comunicacioness asíncronas Comunicacione Como es sabido, la comunicación asíncrona, también llamada “no bloqueante”, es aquella en la que el emisor envía un mensaje y continúa con su funcionamiento normal sin esperar a que el receptor lo procese. El caso contrario es la comunicación síncrona, en la que el emisor envía el mensaje y espera (se bloquea) hasta que recibe la respuesta o transcurre el tiempo de espera. Los sistemas de mensajería (MOM, Message Oriented Middleware) se encargan de proporcionar este tipo de comunicación entre aplicaciones corporativas de una forma sencilla, robusta y fiable. Son mucho más ampliamente escalables que aquellos basados en conexiones directas o a través de llamadas a procedimientos remotos (RPC), y uno de los campos en los que son más utilizados es en el control de flujo (workflow) de información de sistemas. En sistemas MOM los participantes de la comunicación no tienen que preocuparse de esperar una respuesta del recipiente, ni siquiera de dónde se encuentra éste, ya que pueden confiar en la infraestructura de mensajería que se encarga de asegurar su entrega. JMS o Java Message Service es la única API de mensajería soportada por J2EE. Los sistemas de mensajería han ido evolucionando desde simples colas asíncronas hasta sistemas elaborados con publicadores, suscriptores, distri-
SOLO PROGRAMADORES nº 124
42
buidores, formateo de mensajes, capacidades de proporcionar calidad de servicio, etc. Dentro de estos sistemas se conoce a los clientes de mensajería en JMS como clientes JMS, al propio sistema como proveedor JMS, y a la aplicación JMS como al conjunto de clientes y proveedores (normalmente uno) que forman el sistema. El cliente JMS que produce el mensaje es conocido como productor y el que lo recibe se conoce como consumidor, aunque un mismo cliente JMS puede actuar a la vez de los dos modos.
Modelos estándar de mensajería JMS nos proporciona dos modelos distintos de mensajería, publicación/suscripción y comunicación punto a punto mediante colas. Se suelen abreviar con “pub/sub” para el primer modelo y “p2p” para el segundo. A grandes rasgos, el modelo publicación/suscripción está pensado para una comunicación “uno a muchos” mientras que el modelo punto a punto lo está para comunicaciones “uno a uno”. Podemos sugerir para el modelo pub/sub el servicio de suscripciones de esta revista. Pensemos en que los lectores se apuntan a una lista mediante una suscripción y los responsables les envían su ejemplar cada mes. Todos y cada uno de ellos reciben una “copia” de la revista, y no es necesario que los lectores se conozcan entre sí. Para el segundo modelo, podemos pensar en un sistema de colas típico, como puede ser las colas en las cajas de un supermercado. En este caso, los clientes buscan una sola de las cajas disponibles, hacen cola hasta que llega su turno y son atendidos por el/la cajero/a. En la figura 1 podemos apreciar el esquema del modelo pub/sub. En este modelo un productor envía un mensaje a un canal virtual llamado tópico. Los consumidores pueden suscribirse a dicho tópico, con lo que recibirían una copia del mensa je; todos los mensajes enviados enviados a un tópi tópico co son entregados a todos los receptores. En este modelo se conoce al productor como publicador y al consumidor como suscriptor. Un aspecto importante en este modelo es que el publicador no conoce nada acerca de los suscriptores, no sabe dónde se encuentran, ni cuantos hay ni lo que hacen con los mensajes. Asimismo, los receptores no pueden http://digital.revistasprofesionales.com
REDES
Sistemas de mensajería con Java Message Service (I)
Figura 1. Modelo pub/sub de mensajería JMS. JMS.
Figura 2. Modelo point-to-point point-to-point de mensajería JMS.
examinar los mensajes pendientes, y tienen que consumirlos tal cual les llegan. Los aspectos importantes de este modelo son los siguientes: No existe acoplamiento entre productores y consumidores, pueden ser añadidos dinámicamente. Cada suscriptor recibe su propia copia del mensaje. Los suscriptores reciben el mensaje sin tener que solicitarlo. Los mensajes publicados en un tópico son automáticamente entregados a los suscriptores. Veamos Vea mos ahora el model modeloo punto punto a punt puntoo en la figura 2. Este modelo se basa en otro esquema. Los clientes JMS envían mensajes a través de canales virtuales llamados colas. Aquí se conoce a los productores como emisores y a los consumidores como receptores. receptores. Se trata de un modelo en el cual los receptores chequean la cola para ver si han recibido algún mensaje, contrariamente a lo que sucedía en el anterior modelo (aunque es el comportamiento por defecto, se puede aproximar al modelo anterior mediante configuración). En una cola puede haber más de un receptor esperando mensajes, aunque solamente uno de ellos va a consumir cada mensaje. Como observamos en la figura 2, el productor se encarga de generar el mensaje y el sistema JMS entrega el mensaje a uno y sólo uno de los potenciales receptores. La especificación no define las reglas que deben seguirse para la distribución de los http://digital.revistasprofesionales.com
mensajes entre los receptores, así que cada fabricante realiza su propia implementación. Este modelo ofrece otras herramientas, como el explorador de colas mediante el cual el receptor es capaz de examinar los mensa jes pendie pendientes ntes antes de consum consumirlos irlos,, de forma que puede descartar alguno de ellos. Esta es una característica diferenciadora del anterior modelo, además de las que explicamos 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 medida que se consumen se van eliminando de la cola. No existe acoplamiento entre emisores y receptores, se pueden añadir dinámicamente, ya que esta es una característica general de los sistemas de mensajería. El porqué de la existencia de ambos modelos tiene su explicación en los orígenes de la especificación JMS. Inicialmente se pensó como una solución para sustituir las APIs de los sistemas de mensajería existentes. En el momento del análisis, unos fabricantes de sistemas utilizaban un modelo y el resto el otro modelo. Así pues, JMS tuvo que dar opción a ambos modelos para que la industria lo aceptase. En realidad la especificación no exige que las implementaciones proporcionen los dos, aunque los proveedores de JMS lo ofrecen. Fundamentalmente, todo lo que se puede hacer con un modelo también se puede
hacer con el otro. Podemos establecer una analogía en relación a qué lenguaje de programación preferimos, sea el que sea, seguro que podremos conseguir el mismo resultado. De la misma forma, la elección del modelo pub/sub o p2p se convierte en una cuestión de preferencias. Ante la existencia de los dos modelos, surge la duda de cuándo elegir uno u otro. La decisión va a depender de los distintos méritos que aporta cada uno. Si se trata de una aplicación en la que nos interesa repartir mensajes a distintos destinatarios sin importarnos si están conectados o no, el modelo pub/sub puede servirnos. Si por el contrario es importante saber que los mensajes llegan, como puede ser el caso de una conversación uno a uno, quizás sea más interesante utilizar el modelo p2p. La variedad de los datos a transmitir también puede ser un punto a tener en cuenta. Podemos aprovecharnos de la facilidad de tópicos que nos ofrece el modelo pub/sub para segregar los diferentes mensajes entre los potenciales destinatarios. El modelo p2p es más adecuado cuando se quiere que el receptor procese el mensaje una sola vez. Otra ventaja, mencionada anteriormente, es que disponemos de un explorador de colas que nos permite echar una ojeada a la cola para ver los mensajes que esperan ser consumidos.
OpenJMS. Instalación y configuración OpenJMS es una implementación libre de la especificación Java Message Service API 1.0.2. La página del proyecto es http://openjms. sourceforge.net.
Instalación La instalación de OpenJMS es muy sencilla, únicamente necesitaremos tener instalado previamente el JRE (en su caso el J2SDK si deseamos modificar el código fuente del proyecto) y seguir unos sencillos pasos. El archivo de instalación es únicamente una estructura de directorios que contiene todo lo necesario para ejecutar OpenJMS en nuestra maquina. El primer paso consiste en descomprimir el archivo de instalación que está disponible en formato .zip y .tar.gz. La estructura de directorios generada al descomprimir el archivo debe ser la mostrada en la figura 3. La carpeta “bin” contiene archivos .sh y .bat para iniciar, detener, y administrar en servidor
43
SOLO PROGRAMADORES nº 124
REDES
Figura 4. Consola del sistema con el servidor OpenJMS OpenJMS en funcionamiento. Figura 3. Estructura Estructura de directorios de OpenJMS.
OpenJMS. La carpeta “config” contiene el archivo “openjms.xml” el cual indica la configuración por omisión del servidor OpenJMS. La carpeta “config/db” contiene scripts SQL para bases de datos OpenJMS. La carpeta “config/examples” contiene varios ejemplos de archivos de configuración para otras necesidades de funcionamiento del servidor. La carpeta “docs” contiene toda la documentación del proyecto, incluyendo información más detallada de esta instalación. La carpeta “lib” contiene los archivos .jar requeridos para ejecutar el servidor OpenJMS y aquellos requeridos por programas cliente que usan OpenJMS. La carpeta “src/examples” contiene el código fuente de varios archivos de ejemplo. Además de esto, hay que crear las siguientes variables de entorno: JAVA_HOME: El directorio raíz de instalación del JRE. OPENJMS_HOME: El directorio raíz de instalación de OpenJMS. Para probar si la instalación se realizó satisfactoriamente iniciamos el servidor desde la línea de comandos. Para Windows: cd %OPENJMS_HOME%\bin startup
Fichero de configuración de OpenJMS
Para UNIX: cd $OPENJMS_HOME/bin startup.sh
Debe aparecer un mensaje indicándonos que el servidor se encuentra ya disponible (véase la figura 4). Para detener el servidor ejecutamos, en el caso de plataformas Windows:
Para UNIX: cd $OPENJMS_HOME/bin shutdown.sh
Configuración La configuración de OpenJMS se realiza a través de la modificación del archivo
cd %OPENJMS_HOME%\bin shutdown
SOLO PROGRAMADORES nº 124
LISTADO 1
44
“openjms.xml”. Simplemente se van agregando los elementos de configuración que necesitemos para el entorno sobre el cual ejecutaremos el servidor; dichos elementos pueden ser para configurar las bases de datos que vamos a utilizar, la seguridad, configuración de tópicos para publicación/ http://digital.revistasprofesionales.com
Sólo Programadores en Formato Digital
Con el respaldo de más de diez años de publicación mensual y sin interrupciones
Entra en http://digital.re http://digital.revistasprofesiona vistasprofesionales.com les.com Suscripció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 ejemplares de la temporada 2003-04
REDES
Opciones de configuración del servidor OpenJMS Configuración
Descripción OpenJMS se puede configurar para usar bases de datos JDBC para JDBC implementar persistencia de mensajes. OpenJMS proporciona opciones de conectividad sobre varios protoConectores OpenJMS colos, utilizando conectores. OpenJMS utiliza JNDI para hacer disponibles al cliente: fábricas de JNDI conexiones, tópicos, y colas. OpenJMS permite configurar la fábrica de conexiones con distintas Fábricas de conexión opciones. OpenJMS proporciona mecanismos para implementar autenticación Seguridad de conexiones. Los destinos son registrados con JNDI por el servidor OpenJMS para Destinos que estén disponibles a los clientes. OpenJMS permite configurar al detalle la manera en que se ejecutaGarbage collection rá el recolector de basura. LISTADO 2
Ejemplo de configuración para habilitar autenticación de conexiones
suscripción y más opciones. Como ejemplo vemos en el listado 1 el archivo de configuración utilizado para ejecutar el ejemplo que acompaña a este artículo. Podemos observar las instrucciones más relevantes para una configuración con un conector RMI, que es la que viene con OpenJMS por omisión al momento de instalarlo. Los posibles elementos de configuración de este archivo se pueden ver en la tabla “Opciones de configuración del servidor OpenJMS”. A continuación vamos a repasar algunos ejemplos de estos elementos de configuración. Configuración JDBC. En el listado 2 se muestra un ejemplo de configuración JDBC. Actualmente OpenJMS
SOLO PROGRAMADORES nº 124
46
esta configurado para ser compatible con JDBC 2.0 y varios sistemas de bases de datos. Además de agregar este fragmento de código a nuestro archivo de configuración, es necesario agregar al CLASSPATH la ruta de nuestro driver JDBC. Configuración de Conectores OpenJMS. OpenJMS proporciona conectividad a través de varios protocolos utilizando conectores. El listado 3 muestra un ejemplo de configuración para habilitar un conector RMI. Los conectores soportados actualmente por OpenJMS son: RMI, TCP, TCPS, HTTP, HTTPS, Embedded. Una ventaja importante de OpenJMS es que nos permite definir múltiples conectores a nuestro servidor s ervidor..
Configuración de seguridad. OpenJMS proporciona configuraciones para realizar autenticación de conexiones. Para ello se utilizan 2 elementos de configuración, “” y “”. “”. El listado 4 muestra cómo utilizar dichos elementos para habilitar la autenticación de conexiones. Como podemos observar, OpenJMS proporciona una amplia gama de características de configuración, lo que lo convierten en un servidor JMS muy versátil. La finalidad de este apartado es mostrar un panorama general de las opciones de configuración de OpenJMS. Para conocer con mayor detalle la información para la configuración, puedes recurrir a la página del proyecto en Internet.
Ejemplo con el modelo pub/sub y OpenJMS Como ejemplo de aplicación JMS ofrecemos el típico chat. Se trata de una sola clase java “ClienteJMSChat.java”, que actúa tanto como suscriptor como publicador de un tópico de mensajes JMS. Por tanto, se trata de un ejemplo del modelo de publicación/ suscripción. Hay que decir que el ejemplo aquí propuesto es realmente exagerado, el hecho de utilizar un sistema robusto como JMS para una aplicación de chat es quizá excesivo, pero sirva como ilustración. Los métodos de nuestra clase son los siguientes: 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 la clase como su propio nombre indica. Verem Ve remos os su conte contenid nidoo a contin continuaci uación. ón. show(). Muestra el mensaje recibido desde el sistema JMS. debug(). Método para ver mensajes de depuración. Separado de “show()” por conveniencia, aunque realmente hacen lo mismo. chatIt(String). Envía un mensaje al tópico JMS. onMessage(Message). Método que debe implementar la clase para recibir mensa jes JMS. close(). Cierra la conexión JMS abierta. En la ejecución del ejemplo, el programa nos va a ir sacando trazas por pantalla, que ayudarán a comprenderlo mejor. http://digital.revistasprofesionales.com
REDES
Sistemas de mensajería con Java Message Service (I)
LISTADO 5
La función main() Pasemos a examinar la función principal “main()”. En primer lugar observamos que salta una excepción si el número de argumentos pasados es inferior a tres. Los argumentos que hay que pasar son: el primero el tópico al cual queremos conectar, el segundo el nombre de usuario que vamos a utilizar y el tercero la contraseña del usuario (obviamente no se permiten en este caso contraseñas en blanco). Más adelante veremos cómo hay que configurar el servidor JMS para que esté disponible el tópico para el cliente. A continuación instanciamos un objeto de la clase “ClienteJMSChat” y la inicializamos con los argumentos anteriores. Una vez hecho esto obtenemos el stream de la entrada estándar para poder leer los mensajes que el usuario LISTADO 6
Parte principal del método main()
ClienteJMSChat chat = new ClienteJMSChat(); //Argumentos: topic - nombre de usuario - contraseña chat.initialize(args[0], args[1], args[2]); //Leer los mensajes desde la consola BufferedReader consola = new java.io.BufferedReader( new InputStreamReader(System.in)); //Bucle hasta que se introduzca el comando de finalización while (true) { String s = consola.readLine(); try { if (s.equalsIgnoreCase(EXIT_COMMAND)) { chat.close(); //Cerrar la conexión break; } else { chat.chatIt(s); } } catch (JMSException jmse) { chat.debug(“Excepcion JMS: “ + jmse.getMessage()); break; } }
Inicializando el servicio de mensajería
//Obtener una conexión JNDI para acceder a los objetos JMS Properties properties = new Properties(); //Propiedades específicas para conectar con OpenJMS properties.put(Context.INITIAL_CONTEXT_FACTORY, CONTEXT_FACTORY); properties.put(Context.PROVIDER_URL, PROVIDER_URL); try { //Obtener contexto inicial JNDI InitialContext context = new InitialContext(properties); //Obtener la factoría JMS TopicConnectionFactory conFactory = (TopicConnectionFactory) context .lookup(TOPIC_CONNECTION_FACTORY); //Crear la conexión TopicConnection 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 JMS Topic topicObj = (Topic) context.lookup(topico); //Crear un publicador y un suscriptor JMS TopicSubscriber suscriptor = sesionS.createSubscriber(topicObj); TopicPublisher publicador = sesionP.createPublisher(topicObj); //Esta misma clase es la que recibe los mensajes suscriptor.setMessageListener(this); ... //Iniciar la conexion, a partir de aquí los mensajes pueden ser // enviados al tópico conexion.start(); } catch (NamingException ne) { throw new RuntimeException(“Error JNDI”, ne); } catch (JMSException jmse) { throw new RuntimeException(“Error JMS”, jmse); }
http://digital.revistasprofesionales.com
escribe. Todo texto que escriba el usuario es pasado al objeto instanciado llamando al método “chatIt()” excepto en el caso de que se corresponda con el comando de salida “EXIT_COMMAND” (también configurable mediante una variable estática) que hará que el programa termine. Si durante la comunicación ocurre un problema en la capa JMS la capturaremos con la excepción correspondiente. En el listado 5 podemos observar la parte principal de este método.
Inicialización JMS Los pasos para inicializar nuestro programa JMS 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úa con ambos roles). 5. Obtener el objeto tópico a través de JNDI. 6. Por cada sesión, obtener un objeto publicador y suscriptor respectivamente, que actúan como agentes de comunicación. 7. Registrar en el suscriptor la clase actual para que reciba los mensajes que se publican en el tópico. 8. Por último, realizar la conexión con el servidor. En el listado 6 podemos ver estos pasos. Las variables que no aparecen declaradas son variables de clase, se puede consultar el código completo para ver su declaración. En concreto y para conectar con JMS, los datos que hay que proporcionar son:
47
SOLO PROGRAMADORES nº 124
REDES
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 mensajes Como nuestra clase implementa el interface “javax.jms.MessageListener”, debemos crear el método “onMessage()” que recibe los mensajes que provienen del sistema JMS cuando algún cliente envía un mensaje al tópico. Según vemos en la implementación, el método recibe un mensaje tipo “Message”, se convierte a un mensaje de tipo texto y obtenemos el texto como cadena para mostrarlo en la consola (véase el listado 7). Por último examinamos cómo se envían los mensajes al tópico. Simplemente creamos un mensaje tipo texto desde el objeto sesión que corresponde al publicador y establecemos la cadena del mensaje que queremos enviar. A continuación utilizamos el objeto publicador para enviar el mensaje al tópico, como vemos en el listado 8. En el código que acompaña a este artículo podemos observar que en los “imports” no se hace referencia a ninguna clase específica de JMS, únicamente al obtener el contexto ini-
cial JNDI es donde especificamos datos propios de OpenJMS, pero incluso esto lo hemos aislado en una variable estática, el código fácilmente puede ser adaptado para que lea dichos datos de un archivo .properties externo, por ejemplo. Para compilar y ejecutar el ejemplo, además del fuente necesitaremos incluir la API JMS y la implementación OpenJMS para el cliente. Los archivos .jar que vamos a necesitar son los siguientes: jms-1.0.2a.ja 0.2a.jar: r: API JMS. jms-1. openjms-client-0.7.6.1.jar: Implementación para clientes OpenJMS.
Ejecutar el ejemplo Para ejecutar el ejemplo, ofrecemos tres opciones:
Importar el proyecto en el IDE Eclipse. Utilizar Ant para compilar, crear el javadoc y ejecutarlo. Utilizar un script .bat (.sh para linux) para ejecutarlo. Para importar el proyecto a Eclipse, utilizaremos la opción “Import” del menú “File”, y especificaremos que se trata de un proyecto externo. También podemos copiar el directorio dentro del workspace de Eclipse, y crear un nuevo 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 con el script correspondiente con el que podremos compilar, ejecutar el ejemplo e incluso crear el javadoc. Por último, para hacerlo más sencillo, proporcionamos los scripts para la ejecución del ejemplo desde consola: “run.bat”(Windows) y “run.sh” (Linux). Deberemos proporcionar los parámetros necesarios a estos scripts, según se ha explicado.
Conclusiones
Figura 5. Ejecución del ejemplo en Eclipse.
Hasta la llegada de JMS, cada proveedor de mensajería definía su propia API. Mientras que cada solución tenía sus propios protocolos, la similitud lógica entre las distintas versiones eran las mismas. Esto hizo posible la existencia de JMS para estandarizar de alguna forma el desarrollo de sistemas de mensajería. JMS se convierte en una API simple y a la vez robusta, para la implementación en nuestras aplicaciones de este tipo de sistemas, con la ventaja de que existen soluciones Open Source ya maduras como OpenJMS que podemos utilizar de una forma productiva.
Sobre el autor Eduardo Millán Martínez ([email protected]) es Ingeniero Técnico en Telecomunicaciones por la Universidad Politécnica de Valencia. Desde diciembre del 2004 trabaja 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 socio activo de javaHispano desde 2002. Actualmente es responsable de Calidad y Administrador del sitio de proyectos de Software Libre: http://www.javahispano.net.
SOLO PROGRAMADORES nº 124
48
http://digital.revistasprofesionales.com
DISEÑO
Together Architect, el enlace entre el problema y la la sol soluc ució ión n JORDI BORJA (Director de Tecnología Tecnología de Borland)
Together Architect es la solución de Borland para dar respuesta a las necesidades de todo arquitecto de software. En este artículo estudiaremos cuáles son estas necesidades y cómo Together Architect puede ayudar a las compañías de software a crear, mantener y comunicar los modelos conceptuales de un sistema a partir de los requisitos. Introducción En el número anterior analizamos las necesidades, actividades y características de trabajo de los Analistas de Negocio, Analistas Funcionales, y Jefes de Proyecto, así como las soluciones proporcionadas por Borland para automatizar y agilizar su trabajo diario. En este número avanzaremos un poco más en el ciclo de vida de desarrollo, e identificaremos las necesidades de perfiles como Arquitectos, Consultores Técnicos, Analistas Programadores, o Responsables Técnicos de Desarrollo. La característica común a todos ellos es la necesidad de trabajar paralelamente con código y modelo, así como la necesidad de poder acceder a los requisitos y a los modelos de negocio. Por supuesto, también es necesario para todos ellos poder trabajar en grupo sobre un repositorio centralizado, en el que residan tanto los modelos como el código. Por último, la mayoría de estos perfiles también necesitan poder ejecutar pruebas unitarias funcionales y pruebas de rendimiento sobre los componentes desarrollados. Borland, en su plataforma SDP (Software Delivery Platform), identifica a todos estos perfiles con el nombre genérico de “Architect”. En realidad, este perfil es cada día más común en los equipo de desarrollo, en los que los programadores clásicos,
SOLO PROGRAMADORES nº 124
50
centrados exclusivamente en el código, han ido evolucionando a perfiles más multidisciplinares que participan en varias de las fases del ciclo de vida de desarrollo, o que, como mínimo, necesitan obtener información de ellas. En este artículo nos referiremos a todos los roles anteriormente señalados con el nombre genérico de “arquitecto”.
El arquitecto y sus necesidades La principal información de partida para los arquitectos es, sin duda, los requisitos de un sistema. El objetivo del arquitecto es modelar dinámicamente infraestructuras complejas y distribuidas a partir de las últimas versiones de los requisitos funcionales, de negocio, operacionales y de arquitectura. Adicionalmente, el objetivo del arquitecto es que todos los miembros del equipo de desarrollo conozcan cuál es su visión del sistema y que conozcan las decisiones y restricciones técnicas que ha definido. Así pues, para un arquitecto, lo más importante será poder integrar el proceso de diseño con el sistema de Gestión de Requisitos, aumentando el control de los cambios en los mismos, y pudiendo garantizar la visibilidad de sus modelos al resto del equipo. Hay que tener en cuenta, además, que para determinados tipos de proyectos y equipos de desarrollo, es necesaria la figura del Analista de Negocio o Funcional, responsable de transformar los requisitos expresados en lenguaje natural en diagramas de negocio (casos de uso, diagramas de estado, etc.). Estos diagramas son los que en terminología MDA (Model Driven Architecture) se han englobado bajo el nombre genérico de Computation-Independet Models (CIM). El arquitecto, en cambio, deberá convertir esos diagramas en modelos computacionales, que podrán ser independientes de la plataforma (PIM) o específicos de una plataforma (PSM). En general, el arquitecto es el responsable de transformar un conjunto de especificaciones (PROBLEMA) en un sistema (SOLUCIÓN). Esta transformación se realiza a través de diferentes pasos, y en cada uno de ellos se usa un conjunto de modelos (típicamente UML en el mundo Orientado a Objetos) que van desde una reprehttp://digital.revistasprofesionales.com
DISEÑO
Together T ogether Architect, el enlace entre el problema y la solución
sentación más abstracta del sistema a una representación más específica sobre la plataforma elegida para la implementación de la solución. Los tres niveles de modelado definidos por MDA deben de poder ser relacionados entre sí. Por ejemplo, debería ser posible poder conocer qué diagramas de clases están relacionados con un requisito concreto, o qué diagramas de secuencia implementan un caso de uso determinado. Además, deberá ser posible que diferentes perfiles dentro de un equipo de desarrollo hayan creado cada uno de estos diagramas. Un arquitecto, como hemos comentado previamente, necesita poder trabajar de forma paralela con código y modelos, disponiendo de herramientas que permitan la sincronización automática entre ambas vistas. Un cambio en el modelo debe poder transmitirse automáticamente al código, y viceversa. Además, como un arquitecto puede participar en proyectos en los que se utilicen de manera combinada múltiples tecnologías y lenguajes de programación, los modelos deben poderse reutilizar para generar código sobre diferentes plataformas. Adicionalmente, un arquitecto necesita aumentar la productividad, eficiencia, y predictibilidad en sus tareas de diseño. Es por ello que la reutilización re utilización de conocimiento a través de blueprints, plantillas o patrones de diseño resulta imprescindible. Por último, un arquitecto necesita poder generar documentación personalizada a partir de los modelos definidos, que incluya las relaciones entre ellos, y las relaciones con los requisitos.
Borland Together Architect Borland Together Architect es la respuesta de Borland a todas estas necesidades y a muchas más. Together Architect es una solución ágil de modelado diseñada por Borland para ayudar a las compañías de desarrollo a crear, mantener y comunicar los modelos conceptuales de un sistema a partir de los requisitos. MDA ya es una realidad
Con una clara orientación al desarrollo orientado por el modelo (MDD), esta herramienta permite hacer realidad la filosofía MDA, permitiendo a los equipos de desarrollo transformar requisitos en código mediante un entorno visual fácil de usar, y con soporte a todos los diagramas del lenguaje UML, incluyendo los definidos en la versión 2.0 de la especificación y OCL (Object Constraint Language). http://digital.revistasprofesionales.com
Integración de Caliber en Together Architect.
Together Architect incorpora integraciones con Borland Caliber RM, Telelogic DOORS e IBM RequisitePro, con el objetivo de que los modelos de negocio sean construidos a partir de las últimas versiones de los requisitos. Integrando con estos productos es posible gestionar la trazabilidad entre requisitos y modelos. Adicionalmente, si se ha elegido Borland Caliber RM para la Gestión de Requisitos, Together Architect incorpora un cliente embebido con toda la funcionalidad del cliente nativo, con el objetivo de que el arquitecto pueda participar en el proceso de Gestión de Requisitos.
arrollo como JBuilder, Eclipse, C++Builder o MS VS.NET. De este modo, es posible que todo el equipo de desarrollo comparta una única visión del sistema, y que cualquier cambio en los modelos sea automáticamente notificado al resto de miembros del equipo de desarrollo. Además, los modelos relacionados con la plataforma están completamente sincronizados con el código. Esto significa que cualquier cambio que realice un programador en el código Java, C#, C++, Visual Basic, etc. a través de una refactorización por ejemplo, será de igual forma visible por los perfiles que trabajen sobre el modelo.
La independencia de la tecnología
El coste de acoplar una arquitectura a una infraestructura concreta, en un entorno tecnológico cambiante como el actual, puede ser muy elevado. Es por ello que Together Architect posibilita crear modelos independientes de la plataforma, permitiendo una rápida adaptación a cambios tecnológicos o a cambios en los requisitos. Por ejemplo, en lugar de definir un sistema en base a un determinado lenguaje de programación, Together permite crear modelos en un lenguaje formal independiente de la plataforma, para posteriormente ser convertidos a la plataforma .NET o a J2EE. El código fuente es generado en un proceso de transformación, de forma que los programadores pueden trabajar posteriormente en ese lenguaje con su entorno de desarrollo preferido. Visión única del sistema sistema
Los modelos de un sistema pueden ser compartidos por Analistas de Negocio (véase Together Designer en el número anterior de Sólo Programadores ) o por los programadores, a través de los diversos plug-ins de Together para entornos de des-
Cohesión total
Como se ha visto, la sincronización y la trazabilidad son las principales características de un desarrollo en el que el modelo conceptual se ha realizado con Together. Por una parte, como hemos comentado, los requisitos están trazados con los elementos del modelo. En segundo lugar, los diferentes modelos pueden enlazarse entre sí, permitiendo, por ejemplo, asociar modelos independientes de la plataforma o de negocio con modelos dependientes de la plataforma. Por último, los modelos dependientes de la plataforma están siempre sincronizados con el código. De esta forma, se consigue cohesionar al equipo de desarrollo, aumentando el control y gestión del cambio, y la visibilidad compartida del sistema. Gracias a su capacidad de mantener código y modelos sincronizados, Together es la solución ideal para realizar ingeniería inversa de sistemas, generando de ese modo modelos a partir de código existente. La ingeniería inversa facilita la comprensión de un sistema y su mantenimiento. En efecto, a través de las capacidades de refactoring, aplicación de
51
SOLO PROGRAMADORES nº 124
DISEÑO
patrones de diseño, auditoría de código y métricas de diseño, Together permite valorar la calidad de un sistema, y facilitar su mantenimiento correctivo y evolutivo. Patrones de diseño
La aplicación de patrones de diseño permite reutilizar soluciones previamente probadas por otros para resolver problemas que se repiten entre proyectos, así como ajustar nuestras aplicaciones a las buenas prácticas de la industria. Together incorpora los patrones de diseño creacionales, estructurales y de comportamiento conocidos como GoF (Gang-of-Four), además de proporcionar los principales patrones de diseño aplicables a la plataforma específica de desarrollo. Pero… ¿qué ocurre si queremos definir nuestros propios patrones de diseño, o buenas prácti-
Patrones de diseño en Together. Together.
go fuente antes de ser entregado, y garantizar la homogeneidad de calidad entre los diferentes miembros del equipo de desarrollo. Por defecto, Together verifica el cumplimiento de las buenas prácticas y nomenclaturas estándares para el lenguaje de programación seleccionado, pero es posible construir un conjunto propio de reglas sintácticas y de programación, que podrá de nuevo ser utilizado y validado en las herramientas de codificació codificación. n. Algo similar ocurre con la calidad del propio diseño. Cuantificar la calidad del diseño Orientado a Objetos en términos de acoplamiento, tamaño, cohesión, complejidad, uso de herencia y polimorfismo, etc. permite conocer la calidad y eficiencia del equipo y de los procesos de desarrollo, y detectar futuros problemas de extensibilidad, flexibilidad, robustez o facilidad de mantenimiento de una solución. Together permite aplicar múltiples métricas cuantificativas de la calidad de un desarrollo en
Auditorías en Together. Together.
cas? Ningún problema: Together es una herramienta totalmente flexible y extensible. Podemos definir nuestros propios patrones de diseño para poder ser reutilizados en otros proyectos, y de esa forma crearnos nuestro propio catálogo de patrones personalizado, que podrán también ser utilizados también desde las herramientas de desarrollo preferidas de los programadores. Garantías de calidad
Otra de las necesidades actualmente más importante para un arquitecto, o Responsable de Desarrollo, es el poder valorar la calidad del código fuente en base a un conjunto de normativas, nomenclaturas, buenas prácticas y guías de estilo, bien universalmente aceptadas (por ejemplo, los blueprints de la plataforma J2EE) o definidos para un cliente o de forma corporativa. Together Together permite auditar auditar el códi-
SOLO PROGRAMADORES nº 124
52
Métricas en Together. Together.
http://digital.revistasprofesionales.com
DISEÑO
Together T ogether Architect, el enlace entre el problema y la solución
Documentación Documentació n en Together.
términos del uso de la Programación Orientada a Objetos, y, cómo no, definir nuestro propio conjunto de métricas. Metodologías
Together es mucho más que una herramienta de modelado. Es una herramienta completa de ingeniería que permite asegurar la calidad de un desarrollo y el cumplimiento de los requisitos de un sistema. Además, es una herramienta que nos ofrece la flexibilidad necesaria para poder continuar utilizando cualquier proceso y metodología de desarrollo. Desde RUP a eXtreme Programming. Tener libertad de elección del proceso de desarrollo, en función del equipo de desarrollo y del proyecto concreto es otra de las grandes ventajas de Together. Documentación
Sin embargo, para tener total flexibilidad a la hora de elegir nuestra metodología de desarrollo, es también necesario que podamos decidir cómo queremos entregar y documentar nuestro sistema. Con Together, es posible generar documentación de todo el modelo a partir de plantillas de documentación personalizables, en formato HTML, RTF o PDF. Podemos seleccionar el formato, la información a incluir y el nivel de detalle. Por supuesto, podremos incluir en nuestro documento de proyecto las relaciones del modelo con el código (y su documentación estándar) y las relaciones con los requisitos de la aplicación. Un único documento para todo el proyecto, generado automáticamente con un simple clic de ratón con la última información disponible.
soporta diagramas no UML de gran importancia y utilidad en los desarrollos actuales, como diagramas Entidad Relación lógicos y físicos (estos últimos con generación de script SQL y sincronización con tablas relacionales), diagramas de XML Schemas , diagramas de modelado de procesos de negocio, modelado en color, y un largo etcétera. Además, permite la exportación/importación de los proyectos conforme al estándar XMI, además de importaciones específicas de diagramas realizados mediante Rose. ¿Y el trabajo en grupo?
Together permite integrar con múltiples soluciones de control de versiones y configuraciones. En el caso de que utilicéis Borland StarTeam como herramienta de trabajo en grupo, Together incluye un cliente embebido que permite no únicamente realizar las actividades típicas de control de versiones, sino trabajar con peticiones de cambio, tareas, foros de
discusión, vistas evolutivas y correctivas, etc. Imaginaros que se produce una petición de cambio en el sistema: automáticamente, los arquitectos responsables de atender a la petición de cambio serán notificados en su herramienta de trabajo, y podrán enlazar los cambios que realicen en el modelo del sistema a la incidencia, permitiendo de ese modo poder conocer qué cambios se han realizado para atenderla. Del mismo modo, la planificación del proyecto que se ha definido, por ejemplo, con MS Project, generará de forma automática tareas para cada uno de los perfiles del proyecto, de forma que cuando abran su herramienta de modelado podrán conocer cuáles son las tareas que debe realizar sin necesidad de consultar el Gantt del proyecto. Adicionalmente, Together permite comparar modelos, para conocer los cambios que se han producido a lo largo del proyecto, compartir diagramas y fragmentos de los mismos entre proyectos, etc.
Conclusiones La edición de Together para el Arquitecto, como hemos visto, no es una solución aislada dentro del ciclo de vida de desarrollo. Está totalmente integrada en la fase de Gestión de Requisitos, así como en la de Programación, y proporciona cohesión y visibilidad a todo el equipo de desarrollo, gracias a la integración de la herramienta con las soluciones de trabajo en grupo líderes en el mercado. En el próximo número analizaremos las soluciones de Borland para los programadores, y mostraremos cómo es posible que éstos accedan desde su herramienta de codificación a los modelos definidos por el arquitecto y cómo mantenerlos en sincronía con el código.
UML… y mucho más
Para terminar el conjunto de capacidades de la herramienta, hay que señalar que Together http://digital.revistasprofesionales.com
StarTeam en Together.
53
SOLO PROGRAMADORES nº 124
DISEÑO
Diseño multiplataforma para aplicaciones C++ (y III) GABRIEL DOS SANTOS DÁVILA
En esta última entrega nos centraremos en conocer algunas clases adicionales de ACE que nos permiten escribir código portable y algunas que implementan patrones de diseño de uso bastante habitual. Introducción Las dos entregas anteriores nos sirvieron para entender hasta qué punto la librería ACE puede ayudarnos a diseñar y escribir aplicaciones C++ multiplataforma. En la entrega que ahora nos ocupa veremos cómo trabajar con la fecha y la hora, cómo gestionar el sistema de ficheros y algunos patrones de diseño que la librería ACE nos ayudará a implementar implementar..
Operar con fechas y horas La función “time()” de C devuelve la cantidad de segundos que han pasado desde el primero de enero de 1970 como un entero largo de tipo “time_t”. La plataforma Unix provee la estructura
“timeval” para encapsular una fecha/hora. Lo importante es que también en este aspecto, diferentes sistemas operativos proveen primitivas diferentes para la gestión de estos datos. La clase “ACE_Time_Value” de la librería ACE provee una interfaz portable que encapsula un valor de tipo tiempo. Puede encapsular un intervalo de tiempo (por ejemplo una determinada cantidad de segundos o microsegundos) o una fecha absoluta. Esta clase permite convertir entre formatos de tiempo de diferentes plataformas. Sus funciones públicas son: set(): Permite establecer el valor de fecha. Hay versiones sobrecargadas para cualquiera de los tipos de fecha disponibles en las distintas plataformas. sec(): Devuelve sólo el componente de segundos del valor encapsulado. Devuelve sólo el componente de usec(): microsegundos del valor encapsulado. Convierte el valor encapsulado msec(): (“sec()”+”usec()”) en un valor de milisegundos y devuelve este valor. También posee operadores de comparación sobrecargados para poder comparar un objeto “ACE_Time_Value” con otros. Para poder usar esta clase es necesario incluir el fichero “ace/ Time_Value.h”. Podemos obtener la hora actual del sistema de la siguiente manera: #include #include Ace_Time_Value hora_actual; ACE_System_Time::get_local_system _time(hora_actual); _time(hora_ actual);
Este código deja en la variable “hora_actual” la hora del sistema.
Acceso al sistema de ficheros
Documentación Documenta ción de la clase “ACE_System_Time”. “ACE_System_Time”.
SOLO PROGRAMADORES nº 124
54
La librería estándar de C++ provee clases de tipo template que nos permiten trabajar fácilmente con el contenido de un fichero e incluso crear ficheros nuevos. Utilizando estas funciones podremos abrir, cerrar, leer y escribir desde y hacia ficheros tanto en modo texto como en modo binario. El punto en el
http://digital.revistasprofesionales.com
DISEÑO
Diseño multiplataforma para aplicaciones C++ (y III)
LISTADO 1
Borrar un fichero del disco
#include #include #include 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 #include #include #include #include
En el listado 1 vemos el contenido del fichero “main.cpp”. En la función “main()” se verifica que el ejecutable haya sido invocado con un parámetro y se utiliza la función “ACE_OS::unlink()” para eliminar el fichero solicitado, no sin antes confirmar la eliminación. Hemos de tener mucho cuidado con el uso de este programa porque en Windows no mueve los ficheros a la papelera de reciclaje sino que los borra directamente y si borramos un fichero por error sólo podremos recuperarlo con una herramienta de recuperación de ficheros borrados y un poco de suerte. La función “ACE_OS::unlink” utiliza las funciones específicas de cada sistema operativo para eliminar el fichero indicado y devuelve un número entero. Si devuelve un valor menor que cero significa que la llamada a la función falló. Esto podría ocurrir porque el fichero está siendo usado y por ello no puede eliminarse, porque no se cuenta con los permisos suficientes para borrarlo o simplemente porque el fichero no existe.
Mostrar todos los archivos de un directorio
void listar_directorio(char* directorio){ ACE_Dirent_Selector dir; dir.open(directorio); for(int i=0;id_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; }
que la librería estándar carece de funcionalidad es en el referente al trabajo con los ficheros en si en lugar de su contenido. Si necesitamos borrar ficheros o listar los ficheros dentro de un directorio no podremos hacerlos utilizando la librería estándar. La navegación de un sistema de ficheros no es igual en Windows que en Unix y por lo tanto necesitaremos utilizar las abstracciones de ACE para realizar estas tareas de forma portable.
http://digital.revistasprofesionales.com
Borrar ficheros El borrado de un fichero es una tarea sumamente simple utilizando ACE. Para comprobarlo haremos una copia del proyecto “Esqueleto” que creamos en la primera entrega y modificaremos el código del mismo para que reciba un nombre de fichero como parámetro de la línea de comandos y, luego de pedir una confirmación, lo borre del disco.
Listar los contenidos de un directorio Para crear una lista de todos los archivos contenidos dentro de un directorio utilizaremos la clase “ACE_Dirent_Selector”. Esta clase implementa un iterador de entradas de directorio basado en la función “scandir” del API POSIX al que se le pueden pasar filtros para limitar los resultados devueltos. Nuevamente partiremos de nuestro esqueleto vacío de la primera entrega y en el fichero “main.cpp” “main.cpp” escribi escribiremos remos el código código del listado 2. El programa recibe como parámetro una ruta del sistema de ficheros (el nombre de un directorio) y muestra todos los archivos y subdirectorios contenidos en éste, incluidos los denominados “.” y “..” que representan al directorio actual y al directorio padre del mismo. Si en lugar de un directorio se indica como parámetro un nombre de archivo, la función “length()” devolverá 0 y el programa no dará ningún error. El operador [] de la clase “ACE_Dirent _Selector” devuelve un puntero a una estructura “dirent” que posee información sobre cada una de las entradas del directorio de la cual sólo nos interesa el nombre, el cual obtenemos por medio de atributo “d_name”, que contiene un char* con el nombre de la entrada. Si en lugar de mostrar sólo el contenido de un directorio quisiéramos mostrar el de un árbol de directorios completo bastaría con cambiar la función “listar_directorio() “listar_directorio()”” para que funcione recursivamente de la siguiente manera:
55
SOLO PROGRAMADORES nº 124
DISEÑO
LISTADO 3
void listar_directorio(char* directorio){ ACE_Dirent_Selector dir; std: st d::c :cou out t << std::str std::string( ing(dir[ dir[i]-> i]->d_na d_name) me) << std::endl; dir.open(directorio); for(int i=0;id_name); } dir.close(); }
Para probar el código debemos compilarlo y ejecutarlo pasando como parámetro un nombre de directorio. Si todo funciona correctamente, veremos por la salida estándar la lista de los archivos contenidos en el directorio y en todo el árbol de subdirectorios. El listado de archivos de este ejemplo incluye todas las entradas de los directorios pero es posible que en algún caso deseemos filtrar el listado mostrando sólo algunas de las que aparezcan. Una posibilidad para hacer esto es agregar un sentencia if antes de mostrar el nombre por salida estándar en la función “listar_directorio”, tal como hacemos en este ejemplo para filtrar las entradas “.” y “..” pero ACE provee una solución similar que ya viene incorporada dentro del framework. Para lograr este objetivo debemos crear una función que actúe como filtro y pasársela como parámetro al método “open” de “ACE_Dirent_Selector”. El primer paso será crear una función con la firma: int nombre_funcion(cons dirent* d)
Esta función será invocada automáticamente por cada entrada de directorio detectada por “ACE_Dirent_Selector” y debe devolver 1 para aceptar esa entrada o 0 para filtrarla. En
#include #include #include #include
Filtrar la lista de archivos
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;id_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; }
nuestro caso, crearemos una función que muestre sólo los ficheros que contengan “.txt” en su nombre y que filtre el resto, pero podría extenderse para filtrar cualquier cosa que 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 de la entrada de la estructura “dirent”, si este nombre corresponde a alguno de los elementos que no deseamos mostrar devuelve 1 y si no devuelve 0. Por último, remplazaremos la invocación al método “open” de la clase “ACE_Dirent _Selector” en la función “listar_directorio” por lo siguiente: dir.open(directorio,dirselector);
En el listado 3 podemos ver la versión final del programa con el filtro activado. Si lo compilamos y ejecutamos, sólo mostrará aquellos ficheros que nos interesan.
Patrones de diseño
Listado de directorios generado por por la aplicación de ejemplo.
SOLO PROGRAMADORES nº 124
56
Dentro de las facilidades de ACE podemos encontrar no sólo clases que nos permiten escribir código portable sino también otros conjuntos de clases que implementan algu-
http://digital.revistasprofesionales.com
DISEÑO
Diseño multiplataforma para aplicaciones C++ (y III)
Site del libro en el que se basa el diseño de ACE.
LISTADO 4
parametros.hpp, parametros.hp p, primera versión
#ifndef PARAMETROS_HPP #define PARAMETROS_HPP class 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
nos frameworks y patrones de diseño de uso habitual también de manera independiente de la plataforma, basándose para ello en las clases Wrapper Façade que hemos visto hasta ahora.
Singleton El patrón Singleton define una técnica para asegurar que sólo existe una instancia de una clase determinada durante todo el tiempo de vida de un programa. Podría entenderse como el equivalente orientado a objetos de una variable global. Se utiliza en ocasiones en que un mismo objeto debe utilizarse en muchas partes del código de un programa, en funciones distintas. Para ello, en lugar de pasar referencias entre funciones a la única instancia, se emplea un Singleton que permita accederla de manera global. ACE provee clases template que permiten de manera muy sencilla transformar cualquier clase en un Singleton. Para ello crearemos en primer lugar la clase en cuestión. Supongamos que tenemos una aplicación cuyos parámetros de configuración se han de mantener en memoria en un lugar centralizado y queremos crear una clase para encapsular el acceso a estos parámetros de
http://digital.revistasprofesionales.com
LISTADO 5
configuración. El objeto que provea esta funcionalidad deberá estar accesible desde toda la aplicación y deberá existir una única instancia para tener centralizado el control de los parámetros. Tenemos aquí un excelente candidato a ser implementado como un Singleton. En primer lugar crearemos la cabecera de la clase que encapsula los parámetros (“parametros.hpp”, véase el listado 4) A continuación crearemos la implementación (“parametros.cpp”). No nos detendremos a describir la implementación completa de las funciones para leer y guardar los parámetros pues no es ese el objetivo del artículo. En cambio, nos limitaremos a definir los métodos necesarios y ver cómo convertir la clase en un Singleton (vea esto en el listado 5). Una vez escrita la clase, haremos las modificaciones necesarias para la implementación del patrón Singleton en el fichero “parametros.hpp” (véase el listado 6). Como podemos ver en el código hemos realizado tres modificaciones. Para implementar el patrón Singleton alcanza con la declaración del tipo “parametros_singleton”. Adicionalmente hemos hecho privado el constructor de la clase parámetros y declaramos a la clase Singleton como friend para evitar que algún programador pueda crear 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 parametro return “”; } void parametros::modificar_parametro( std::string nombre, std::string valor){ //modifica el valor de un parametro }
LISTADO 6
parametros.hpp, parametros.hp p, segunda versión
#include #include #include class parametros{ friend class ACE_Singleton; 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_singleton;
57
SOLO PROGRAMADORES nº 124
DISEÑO
instancias de la clase parámetro por su cuenta, salteándose la restricción del Singleton. La clase template “ACE_Singleton” recibe dos parámetros. El primero es la clase a la que queremos convertir en Singleton y el segundo es el tipo de mecanismo de exclusión mutua a utilizar para sincronizar el acceso de los distintos threads a la única instancia del Singleton. En aplicaciones de un único thread se puede usar “ACE_Null _Mutex”, en cuyo caso no se aplicará ningún mecanismo de exclusión. Si estamos creando una aplicación multithreaded, es necesario que la declaración del Singleton utilice “ACE_Recursive “ACE_Recursive_Thread_Mutex”: _Thread_Mutex”: typedef ACE_Singleton parametros_singleton;
En este caso el Singleton se encargará automáticamente de sincronizar los accesos desde múltiples threads. Como nuestra aplicación tendrá un sólo thread no utilizaremos mecanismo de exclusión mutua. Una vez que hemos creado la clase Singleton veremos como podemos utilizarla en un programa de prueba. El acceso a la única instancia del Singleton se efectúa a través de un método llamado “instance()” que devuelve un puntero a una instancia de la clase que el Singleton está encapsulando. El programa de ejemplo invoca dos veces a la función “instance()” y compara los resultados devueltos para verificar que se trata de la misma instancia (véase el listado 7). La penúltima línea de la función “main” está comentada. Esta línea intenta crear una instancia de la clase parametros de manera directa por medio de “new”. Si quitamos las barras de comentario de esta línea e intentamos compilar ese código, el compilador nos devolverá un error porque la clase “parametros” no tiene ningún constructor público. Por eso para que la clase “ACE_Singleton” pueda crear instancias ha sido declarada como friend.
Acceptor-Connector Este patrón se aplica en servicios que deben cooperar y se encuentran distribuidos en distintas máquinas. Para poder trabajar en con junto jun to debe deberán rán esta estable blecer cer una cone conexió xión n de red entre si y el objetivo de este patrón es permitir separar la lógica requerida para establecer las conexiones de la lógica que realiza las tareas reales del servicio o lógica de aplicación. Los roles de una aplicación que utiliza una conexión de red pueden dividirse en dos: Rol de conexión: Determina el papel que juega en en el establecim establecimiento iento de de una conecone-
SOLO PROGRAMADORES nº 124
58
LISTADO 7
main.cpp
#include “parametros.hpp” #include #include 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; }
xión. Puede ser un papel activo (el que solicita la conexión) llamado Connector o un papel pasivo (el que está escuchando a la espera de peticiones) llamado Acceptor. Rol de comunicación: Determina si el componente cumple el papel de servidor o de cliente (o ambos) durante la utilización de la conexión. La aplicación de este patrón separa claramente los dos tipos de roles. Además, una vez escrito el código para establecer una conexión (ya sea de manera activa o pasiva) es muy poco probable que éste cambie. Por el contrario, el código relacionado con el rol de comunicación seguramente deberá evolucionar con el tiempo y ésta evolución se verá simplificada por el patrón Acceptor-Connector. La lógica de trabajo del componente se implementa en un Service Handler o Gestor de Servicios. También es importante destacar que si bien este artículo se refiere a la aplicación de este patrón en conexiones de red por ser el ejemplo más claro y fácil de comprender,, el mismo puede aplicarse a cualprender quier tipo de comunicación entre procesos y ACE provee la flexibilidad para hacerlo. La clase “ACE_Svc_Servi “ACE_Svc_Service_Handler” ce_Handler” provee la base para implementar el código del comportamiento de la aplicación. Esta es una clase template cuyos parámetros son el tipo de Stream (o corriente de datos) que se utilizará para conectarse con el componen-
te remoto y el mecanismo de sincronización de threads a utilizar. Si quisiéramos implementar el servidor echo de la primera entrega de esta serie usando este patrón, comenzaríamos por declarar la clase handler del servicio: class echo_svc_handler : public ACE_Svc_Handler{ public: int svc (); };
Esta clase hereda de la clase “ACE_Svc _Handler”. El parámetro “ACE_SOCK _Stream” de la clase template indica que los datos hacia el otro extremo de la conexión se enviarán a través de un objeto de esa clase, “ACE_INET_Adrr” describe el tipo de dirección que identificará el otro extremo de la conexión y el parámetro “ACE_NULL _SYNCH” sirve para indicar que no se ha de hacer ningún control de sincronización de threads. Para la implementación del comportamiento de la clase, sólo necesitamos sobrescribir el método virtual “svc()” de “ACE_Svc_Handler” de la manera en que se muestra 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.
http://digital.revistasprofesionales.com
DISEÑO
Diseño multiplataforma para aplicaciones C++ (y III)
En la documentación de ACE podemos encontrar un detalle de todos los métodos disponibles. Para acceder al stream que nos comunica con el otro extremo de la conexión usamos la función “peer()” de la clase “ACE_Svc_Handler”, que nos devuelve una referencia a un objeto de tipo “ACE_SOCK _Stream” o más precisamente del tipo especificado como primer parámetro de la clase template. A diferencia del ejemplo de la primera entrega, en este servidor echo no aparece el código relacionado con aceptar y establecer la conexión mezclado con el código necesario para que el servidor haga su trabajo lo cual mejora la separación de responsabilidades. Por último debemos escribir el código para que nuestro servidor echo comience a escuchar y acepte conexiones. Este código sería similar al siguiente: typedef ACE_Acceptor echo_acceptor; ACE_INET_Addr port_to_listen(7); echo_acceptor acceptor(port_to_listen);
Al recibir una dirección en su constructor el acceptor comienza inmediatamente a escuchar en ella. Por cada petición que el acceptor reciba, crea una instancia de la clase “echo_svc_handler” e invoca al método “svc()”. De esta manera, habrá una instancia independiente para gestionar cada petición, eso sí, todas en el mismo thread. El código explicado en este ejemplo es mucho más limpio y elegante aún que el de la primera entrega, que ya representaba una mejora significativa sobre el método de programación estándar. He aquí la utilidad de los patrones de diseño.
Reactor El patrón de diseño Reactor simplifica el desarrollo de aplicaciones orientadas a eventos. Estos eventos pueden ser disparados por señales del sistema operativo, algún mecanismo de comunicación entre procesos (también conocidos como IPC por sus siglas en inglés) o simplemente por el paso del tiempo. Así como el objetivo del patrón AcceptorConnector es separar la responsabilidad de establecer la conexión de red del código de trabajo de la aplicación, el patrón Reactor tiene como principal objetivo separar código que detecta la ocurrencia del evento deseado del código de trabajo de la aplicación. Estos aspectos están encapsulados por las clases “ACE_Reactor” y “ACE_Event_Handler” respectivamente.
http://digital.revistasprofesionales.com
Documentación Documentac ión de la clase “ACE_Reactor”. “ACE_Reactor”.
La clase abstracta “ACE_Reactor” provee una interfaz portable para un conjunto de subclases que encapsulan llamadas a funciones como “WaitForMultipleObjects()” de Windows o “select()” de Unix, logrando de esta manera una implementación completamente multiplataforma de este patrón de diseño. Un “ACE_Reactor” monitorea algún evento determinado y mantiene una lista de objetos interesados en ser notificados cuando el mismo ocurra. La clase reactor se encarga de notificar a todos los objetos interesados cuando ocurre el evento. Los objetos de esta lista deben ser de una clase derivada de “ACE_Event _Handler”. Disponemos de varias funciones para gestionar la lista de “event handlers” registrados: register_handler(): Permite agregar un handler a la lista. remove_handler(): Permite eliminar un handler de la lista. detener suspend_handler(): Permite temporalmente el envío de notificaciones a un handler determinado. resume_hander(): Reinicia el envío de notificaciones 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 función “WaitForMultipleObjects()” “WaitForMultipleObjects()”.. ACE_TP_Reactor() permite extender el patrón a un pool de threads. La función “handle_events()” hace que el reactor comience a monitorear el evento seleccionado. Como ya hemos mencionado el código específico de la aplicación es encapsulado
por una subclase de “ACE_Event_Handler”. Esta clase base define métodos virtuales cuyo nombre comienza con “handle_” y que deben ser anulados en la subclase para implementar el comportamiento requerido: Se utiliza cuando el handle_input(): reactor moniterea una conexión de red a la espera de datos. handle_signal(): Se utiliza cuando el reactor monitorea una señal del sistema operativo como con “WaitForMultipleObjects()” por ejemplo. handle_close(): Sirve para colocar aquí el código necesario para liberar cualquier recurso que el event handler tuviera en uso. handle_timeout(): Es llamado cuando el reactor está monitoreando un temporizador y ocurre cuando el temporizador alcanza el tiempo indicado.
Conclusiones A lo largo de estas tres entregas hemos cubierto una parte de la funcionalidad de ACE. Esta librería no sólo posee un excelente diseño de arquitectura sino que nos facilita la creación de un diseño igual de bueno en nuestro propio código. Un buen diseño, flexible y claro, debería ser siempre uno de nuestros objetivos a la hora de diseñar una aplicación. ACE es además muy eficiente y compatible con una amplia variedad de compiladores y sistemas operativos. Esto agregado a la enorme cantidad de funcionalidad que provee la convierte en una opción ideal para la implementación de aplicaciones en las cuales la independencia de la plataforma es una necesidad.
59
SOLO PROGRAMADORES nº 124
DUDAS
Preguntas y respuestas ADOLFO ALADRO GARCÍA
En una aplicación en C/C++ para Windows, ¿existe alguna forma de hacer que se llame a 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. Este mecanismo puede emplearse precisamente para hacer que la llamada a una función se ejecute con un 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 principal de la aplicación. El segundo es una constante “define” que permite identificar al temporizador. El tercer parámetro indica el número de milisegundos que transcurrirán antes de que salte el temporizador. Finalmente, el último parámetro es un puntero a la función responsable de procesar los mensajes del temporizador. Cuando este parámetro es “NULL” los mensajes llegan al procedimiento de ventana principal de la aplicación. Cada vez que el temporizador salta el sistema hace llegar a la función de procesamiento un mensaje del tipo “WM_TIMER”. “WM_TIMER”. El parámetro “wParam” del mensaje representa el identificador del temporizador y el parámetro “lParam” es un puntero a la función de procesamiento que se pasó como parámetro. Así por ejemplo si el procedimiento de
Características de los componentes de una interfaz Propiedad FileChooser.ancestorInputMap FileChooser.cancelButtonMnemonic FileChooser.detailsViewIcon FileChooser.directoryOpenButtonMnemonic FileChooser.helpButtonMnemonic FileChooser.homeFolderIcon FileChooser.listViewIcon FileChooser.newFolderIcon FileChooser.openButtonMnemonic FileChooser.saveButtonMnemonic FileChooser.upFolderIcon FileChooser.updateButtonMnemonic FileView.computerIcon FileView.directoryIcon FileView.fileIcon FileView.floppyDriveIcon FileView.hardDrive ventana principal de la aplicación se define de la siguiente manera: ( HWND
hwnd,
UINT
uMsg,
WPARAM wParam, LPARAM lParam )
}
Los mensajes procedentes de los temporizadores pueden procesarse tal y como se muestra a continuación: switch (uMsg) { ... case WM_TIMER:
60
} } }
...
SOLO PROGRAMADORES nº 124
...
LRESULT CALLBACK WindowProcedure
{
Documentación de la función “SetTimer” Documentación (http://msdn.microsoft.com/library/default .asp?url=/library/en-us/winui/winui/ windowsuserinterface/windowing/timers/ timerreference/timerfunctions/settimer.asp).
{ if (wParam==IDT_TIMER1) { KillTimer(hwnd, IDT_TIMER1);
Estoy desarrollando un Applet firmado que emplea un componente “JFileChooser” para que el usuario pueda salvar unos ficheros y me gustaría poder personalizar el componente para que algunos botones no salieran, o salieran con los iconos que yo quiero, etc. He estado revisando el API y no encuentro ningún método que me permita hacer estas cosas, ¿es posible? En principio la capacidad de personalización del componente “JFileChooser” es bastante limitada en lo que al API se refiere. No obstante sí que existe un buen número de propiedades que puedes establecer empleando la clase “UIManager”. Esta clase sirve, entre otras muchas cosas, para fijar las característica característicass relativas al aspecto, y en algunos casos incluso al comportamiento de los componentes que se emplean en una aplicación o Applet Java. La http://digital.revistasprofesionales.com
¿Luchas contra el caos? …ahora puedes solucionarlo !!
Consigue por sólo 6 euros un archivador de revistas valorado en 5,41 euros y 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 03 o 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 REVIST AS PROFESION PROFESIONALES ALES - C/ Valent alentín ín Beato, Beato, 42 - 3ª plta. - 28037 Madrid Madrid *en opción contrareembolso 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, (nombre, dirección y número de cuenta completo) completo)
DUDAS
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
Aspecto de un componente “JFileChooser” al que se le ha eliminado el botón de detalles.
LISTADO 2
Y posteriormente se muestra la lista de la siguiente forma:
}
Cambios en los componentes
if (component instanceof AbstractButton) { Icon icon = ((AbstractButton)component).getIcon(); if (icon!=null) { String sIconClassName = icon.getClass().getName(); if (sIconClassName.indexOf( (sIconClassName.indexOf(“MetalIconFactory$FileChoo “MetalIconFactory$FileChooserDetailViewIcon”)!=-1) serDetailViewIcon”)!=-1) { component.getParent().remove(component); } } }
tabla “Características de los componentes de una interfaz” muestra un resumen de esto. La primera columna contiene el nombre de la propiedad y la segunda el tipo de objeto que espera recibir. Obsérvese también que el primer grupo de propiedades se refieren al componente “JFileChooser” propiamente dicho, mientras que el segundo grupo se refieren no a un componente sino a la clase “FileSystemView”, que es la que se emplea para mostrar los directorios y ficheros dentro de un componente “JFileChooser”. El método “put” de la clase “UIManager” se define como sigue: public static Object put(Object key, Object value)
El primer parámetro es un objeto que sirve para identificar la propiedad que se desea establecer, y el segundo es otro objeto con el valor de dicha propiedad. Así por ejemplo, si antes de crear una instancia del componente “JFileChooser” se ejecuta una línea como la que sigue: UIManager.put ( “FileChooser.detailsViewIcon”, new ImageIcon(“my_detailsviewicon.gif”); );
Con el mecanismo descrito anteriormente se pueden personalizar algunos aspectos de la apariencia de un componente “JFileChooser” pero realmente no se pueden hacer cosas tales como eliminar uno de los botones. Para este tipo de tareas tampoco existen métodos en el API. La única solución pasa por “deconstruir” el componente paso a paso, hasta dar con todos los componentes que a su vez forman parte de él, y entonces llevar a cabo la personalización que sea necesaria. El método del listado 1 permite explorar todos los componentes que forman parte de un componente dado. El primer parámetro representa el componente a explorar y el segundo parámetro es un objeto de tipo “ArrayList” donde se irán almacenando las referencias de todos los componentes encontrados. En primer lugar se añade a la lista el componente que se pasa como parámetro. Si ese componente es una instancia de la clase “Container” entonces significa que puede contener otros componentes. La colección de componentes que contiene se obtiene empleando el método “getComponents”. Esta colección se recorre y se llama recursivamente de nuevo a la misma función para cada uno de los elementos. Si se emplea esta función haciendo: JFileChooser jFileChooser = new JFileChooser();
El icono que aparecerá en el botón de detalles del componente será el correspondiente a la imagen “my_detailsviewicon.gif”. “my_detailsviewicon.gif”.
SOLO PROGRAMADORES nº 124
62
ArrayList alComponents = new ArrayList(); getComponents(jFileChooser, alComponents);
int iSize = alComponents.size(); for (int i=0; i
Se obtiene una lista de todos los componentes que forman parte de un objeto de tipo “JFileChooser”. Esta lista tiene el siguiente aspecto: javax.swing.JFileChooser[...] javax.swing.JPanel[...] javax.swing.JPanel[...] javax.swing.JButton[...] javax.swing.Box$Filler[...] ...
Evidentemente, una vez que se tiene acceso a cada uno de los componentes individuales, se pueden hacer cualquier tipo de cambios, como por ejemplo el que se muestra en el listado 2. En este ejemplo se parte del supuesto que se está empleando el look &feel llamado “metal”. Si la clase del icono que emplean un botón contiene la cadena de texto “MetalI conFactory$FileChooserDetailViewIcon” significa que se trata del botón de detalles y entonces se elimina del componente simplemente utilizando el método “remove” de su padre. Finalmente, este mecanismo es tan potente como peligroso ya que en realidad se están accediendo a las propiedades internas de un componente “JFileChooser”, lo que significa que no sólo podemos cambiarlo sino que además podemos hacer que deje de funcionar correctamente. http://digital.revistasprofesionales.com
LIBROS
Desarrollo web con PHP Desarrollo web con PHP y MySQL AUTORES: Luke Welling, Laura Thomson EDITORIAL: ANAYA ISBN: 84-415-1569-7 PÁGINAS: 91 9111 LUGAR Y AÑO DE PUBLICACIÓN: Madrid, 2003 IDIOMA: Castellano OBSERVACIONES: Incluye CD-ROM con el código fuente de los ejemplos y herramientas para el desarrollo
PHP y MySQL son conocidas tecnologías de código abierto que resultan muy útiles para diseñar de forma rápida y eficaz aplicaciones web dirigidas a bases de datos. Como el lector sabrá, PHP es un potente lenguaje de secuencia de comandos diseñado específicamente para crear aplicaciones web
Desarrollo con PHP, Apache y MySQL AUTORES: Michael K. Glass, Yann Le Scouarnec, Elizabeth Naramore, Gary Mailer, Jeremy Stolz, Jason Gerner EDITORIAL: ANAYA ISBN: 84-415-1755-X PÁGINAS: 704 LUGAR Y AÑO DE PUBLICACIÓN: Madrid, 2004 IDIOMA: Castellano
El principal objetivo de este libro es ofrecer una pequeña muestra de lo que un diseñador web puede realizar con la ayuda de PHP, Apache y MySQL. Esta obra pretende guiar en la creación de sitios web utilizando el modelo AMP (Apache, MySQL y PHP) de código abierto. El lector apren-
PHP 5 AUTOR: Francisco Charte Ojeda EDITORIAL: ANAYA ISBN: 84-415-1770-3 PÁGINAS: 655 LUGAR Y AÑO DE PUBLICACIÓN: Madrid, 2004 IDIOMA: Castellano OBSERVACIONES: Incluye CD-ROM con el software necesario para llevar a cabo proyectos en PHP 5 sobre diferentes sistemas operativos
PHP se ha convertido en el estándar para la creación de páginas de servidor y aplicaciones web, constituyendo la nueva versión la renovación más importante de los últimos años. Este libro describe
SOLO PROGRAMADORES nº 124
64
con distintas prestaciones de forma rápida y segura. MySQL es una base de datos rápida y fiable que se integra a la perfección con PHP y que resulta muy adecuada para aplicaciones dinámicas basadas en Internet. Este libro enseña a utilizar estas herramientas de forma conjunta para obtener aplicaciones web eficaces e interactivas, desde los formularios de pedidos más sencillos hasta los sitios de comercio electrónico más complejos y seguros. Los temas tratados en esta obra podrían resumirse en el diseño de bases de datos, creación de sitios de comercio electrónico, construcción de un carrito de la compra, creación de gestores de listas de correo, creación de foros web, generación dinámica de documentos PDF etc.
derá a instalar PHP, Apache y MySQL, aprenderá a crear páginas web con PHP, aprenderá a administrar y a proteger bases de datos y, por último, aprenderá a integrar sus creaciones en plataformas de comercio electrónico con otras tecnologías. Cuando el lector haya terminado, podrá crear sitios web dinámicos y bien diseñados con la ayuda de herramientas de código abierto. A modo de resumen, diremos que los temas que aborda esta libro son el lenguaje PHP, cómo acceder a una base de datos, creación de formularios, formas de permitir a los usuarios el acceso a la información de la base de datos, creación de aplicaciones de comercio electrónico, etc.
todas las novedades que incorpora PHP y demuestra su uso en la práctica, con proyectos reales de nivel profesional. Los primeros capítulos del libro ayudarán al lector a instalar PHP 5 sobre windows, GNU/Linux y Mac OS X, ya sea con Apache 1.3, Apache 2.0 o Internet Information Server. Después, capítulo a capítulo, el lector irá configurando las extensiones necesarias para cada tipo de proyecto. Los temas que aborda este libro se centran en el estudio de la sintaxis de PHP 5, acceso a bases de datos, uso de cookies, XML y SOAP para la creación de servicios web con PHP, creación de un servicio de chat, generación de informes, etc.
http://digital.revistasprofesionales.com
CD-ROM
Contenido del CD-ROM Fuentes
Programación
Juegos de calidad comercial en J2ME (III)
OpenJMS 0.7.6.1
El lector estará notando, después de leer esta tercera entrega del curso sobre programación avanzada sobre móviles Nokia, que realmente se puede hacer todo o casi todo desde una aplicación J2ME si se conoce el API del terminal destino. El CD-ROM incluye, en este apartado, códigos de ejemplo para manejar la luz de la pantalla, la vibración del teléfono, la cámara de fotos, el sonido, etc.
Este es el servidor de mensajería utilizado en la serie de artículos “Sistemas de mensajería con Java Message Service”. OpenJMS proporciona una implementación del API JMS robusta y profesional, es de fácil instalación y es libre.
OpenSTA 1.4.2
Aspect# 2.1.0.0 Programación distribuida distribuida en .NET (II) En esta segunda entrega sobre programación distribuida en .NET nos hemos centrado en la solución .NET Remoting. El lector encontrará en el CD-ROM, en la sección dedicada a este artículo, los ejemplos que se han ido comentando así como las instrucciones para su compilación y ejecución.
La Programación Orientada a Aspectos, pese a ser desconocida por muchos, en realidad ya está al orden del día, y en este sentido hemos querido acercar este mundo al lector. Aspect# es un framework que permite programar bajo este paradigma a los programadores C#.
Sistemas de mensajería con Java Message Service (I) Esta primera entrega ha servido para introducir al lector en el mundo de la mensajería y, concretamente, a la API JMS. El ejemplo que se incluye en esta sección del CD-ROM es de lo más ilustrativo, además se ofrecen distintas formas de ejecución del mismo: Importando el proyecto desde Eclipse, con Ant o por línea de comandos.
Diseño multiplataform multiplataformaa para aplicaciones C++ (y III) Seguramente el lector, antes de leer este artículo, desconocía cómo hacer un programa C++ que trabajara con el sistema de ficheros (listando directorios, borrando ficheros, etc.) y que dicho programa fuera compilable en distintas plataformas (Windows, Linux, etc.). Los ejemplos ofrecidos en este punto demuestran cómo hacer esto, y además nos enseñan a implementar el patrón de diseño Singleton con la librería ACE.
SOLO PROGRAMADORES nº 124
66
NUnit 2.2.0 NUnit debería ser una herramienta de interés para aquellos programadores .NET que quieran hacer pruebas extremas sobre el código que escriben.
XAML (IV) A estas alturas, y después de 4 entregas sobre XAML, podríamos decir que ya casi somos unos expertos. Los ejemplos propuestos en este punto ilustran cómo conformar interfaces gráficas XAML obteniendo la información de distintos orígenes de datos.
Conocer los niveles de carga de trabajo y estrés que nuestra aplicación web puede soportar es útil para detectar, en última instancia, los puntos débiles o los cuellos de botella. OpenSTA es un avanzado sistema que nos permite definir un script con la navegación deseada, y luego aplicar fuertes cargas de trabajo contra nuestro site.
Yet Another Another Forum.net 0.9.9 Para quienes estén desarrollando un portal con ASP.NET, puede ser de gran ayuda un recurso como YAF. Este paquete de software contiene una implementación completa de un foro de discusión escrito en ASP.NET, C# y con SQL Server. La idea es que cualquiera debería poder incluir en su portal web ASP.NET este foro de manera directa.
NHibernate 0.7.0.0 NHibernate es la alternativa a Hibernate en el mundo .NET. Como el lector sabrá, puesto que en el número 120 de Sólo Programadores fue objeto de estudio, Hibernate es la solución para la persistencia de objetos en BBDD relacionales del mundo Java. Por su parte, NHibernate es su homólogo del mundo .NET.
Log4J 1.2.9 Log4J es una aplicación que permite gestionar de forma elegante, mediante ficheros de configuración externos, los tan famosos “printf” (o la instrucción de turno para escribir por la salida estándar) que nos ayudan, en tiempo de desarrollo y pruebas, a controlar la ejecución de nuestro programa.
Remoting.Corba 1.3.1 Tal como se ha descrito en el artículo “Programación distribuida en .NET (II)”, Remoting.Corba permite agregar a nuestro entorno .NET la capacidad de comunicarse con objetos mediante CORBA.
JSP Standard Tag Library 1.1
Joda-Time 1.0
El desarrollo con la tecnología JSP ha sido muchas veces criticado por producir código muy poco legible, mantenible y elegante, al mezclar código Java con lenguaje de marcas HTML. JSTL pretende ofrecer una solución a este problema, ya que permite tener por un lado el código de la presentación y por otro lado el código de la lógica de negocio.
Este producto ha sido presentado en la sección de la comunidad javaHispano. Su objetivo es ofrecer a la comunidad Java una librería que haga más sencilla y eficiente la gestión de la fecha y la hora desde aplicaciones Java.