A meternos con Java

Es deporte olímpico desde hace tiempo meterse con Java. Como plataforma es lenta, insegura e inútil. Como lenguaje, causa daños cerebrales irreparables a los programadores que lo utilizan. Para colmo, ahora ya no es propiedad de Sun (que era bastante molona), sino que ha sido absorbida por la malvada Oracle.

Pues para mi sigue siendo una de las herramientas más útiles que tenemos a nuestra disposición; potente, gratuita y open source.

Comencemos por la última moda. Java es inseguro.

Vaya por delante que servidor navega con todos los plugins desconectados por defecto. Ni Flash, ni Java, ni incluso el lector de PDFs de Chrome cargan si no hago click explícito en ellos. Los navegadores son probablemente el programa de mayor riesgo de seguridad, siendo los banners de publicidad y las webs invadidas los mayores riesgos; innumerables webs sufren ataques que inyectan código malicioso en ellas y los banners de publicidad son una manera relativamente viable de colar código malicioso en webs “de confianza”. Poco software más procesa más datos potencialmente hostiles de Internet.

Todo el código expuesto a Internet ha sufrido vulnerabilidades; los clientes de correo, todos los navegadores y, especialmente, todos los plugins, han sufrido vulnerabilidades graves.

Java no es la excepción, ni mucho menos.

Dos incidentes recientes han sido especialmente notables. En abril, una vulnerabilidad de Java que sólo afectaba a ordenadores con OS X ejecutando la máquina virtual Java distribuida por Apple fue harto comentada al ser uno de los primeros malware afectando en masa a Macs. Gran parte de los medios cargaron contra Oracle por hacer de los ultraseguros Macs un coladero (por ejemplo, tras una rápida búsqueda en Google, podemos leer esto).

En general, estos artículos convenientemente omiten el hecho de que la vulnerabilidad había sido solventada meses antes por Oracle y había distribuido el parche. ¿Por qué no a los Macs? Pues sencillamente porque Oracle y Apple tenían un acuerdo mediante el cual es Apple la responsable de distribuir Java a los Macs (esto probablemente está vinculado a que Apple había escogido Java como una de las plataformas “oficiales” de desarrollo de aplicaciones oficiales para OS X tiempos atrás). Apple por supuesto era consciente de la vulnerabilidad y había escogido no distribuirla.

En mi opinión, es completamente irracional culpar a Oracle/Java de este problema- la culpa reside plenamente en Apple; los agujeros de seguridad son inevitables y lo importante es cómo se gestionan. En este caso, mal gestionado por Apple. Podemos argumentar que Oracle hizo mal en ceder la responsabilidad de seguridad a Apple (porque en efecto, hemos visto que no ha sido buena ídea), pero al menos Oracle a partir de esto ha asumido esta responsabilidad de nuevo.

El segundo incidente que tiene lugar estos días no es así, es una vulnerabilidad de Java. Según se dice, unos investigadores polacos habían alertado a Oracle de ella meses atrás y paralelamente, programadores maliciosos la habrían descubierto también y comenzado a explotar. Si esto es así, podemos cuestionar la diligencia de Oracle en tapar el agujero. Podríamos darles el benefici0 de la duda, pues otros agujeros reportados por el grupo polaco fueron parcheados diligentemente, y uno podría pensar que existe un motivo razonable por el que ese agujero en concreto se haya demorado más- pero creo que no es un argumento sólido. Yo valoro negativamente la actuación de Oracle en este incidente.

Pero en definitiva, dos incidentes de notoriedad; el mayor incompetente en esta fiesta es claramente Apple, seguido de Oracle (a bastante distancia en mi opinión). Creo que es deshonesto intelectualmente machacar a Oracle sin criticar a Apple por encima- y más aún si ignoramos que los agujeros son inevitables, que el histórico del manejo de los agujeros de Java ha sido siempre bastante correcto.

Pero vaya, si sólo hemos de aprender una única cosa de todo esto, es a navegar con los plugins desconectados.

Por otra parte, como siempre que se oye la palabra Java, sale un coro de programadores maltratados alegando que Java les ha jodido la vida. Complejo, pesado, incómodo, etc.

El problema es que para lo que se usa Java, pocas alternativas hay. Sí, para escribir programas pequeños existen bastantes soluciones mejores, como Python o Ruby; Haskell, C++, Matlab, Erlang, R, bash son claramente mejores en otras áreas más específicas.

Pero para escribir aplicaciones “administrativas” grandes, no existe nada mejor. Python y Ruby son dinámicos, lo cual impide de entrada que existan herramientas suficientemente potentes como para poder refactorizar y analizar código con un mínimo de fiabilidad- en un proyecto suficientemente grande esto supone un coste en tiempo suficiente como para compensar cualquier otra ventaja que se pudiera tener. Herramientas como Eclipse son extremadamente valiosas para el desarrollo a gran escala y simplemente no pueden existir tal cual para un lenguaje dinámico (nótese que por ejemplo Google hace análisis sobre lenguajes dinámicos, pero lo hace añadiendo información de tipos al código- con lo cual se gana en herramientas, pero se pierde la supuesta ventaja de los lenguajes dinámicos).

La única alternativa de calado viable es .NET. Sin embargo, es una herramienta con costes que impone unas restricciones bastante duras (e.g. nos obliga a pagar caras licencias en el servidor, lo cuál supone un impedimento importante a los escalados horizontales). Para algunos serán aceptables, para otros lo hace inviable.

Sí, Java como lenguaje sufre muchas carencias; falta de lambdas y una API muy potente pero poco amigable (básicamente, para hacer cosas sencillas, es muy muy fastidioso- y uno quiere hacer cosas sencillas casi siempre); las lambdas suponen un serio inconveniente bastante insalvable (hay cosas que se expresan con mayor concisión y claridad con ellas), pero lo de la API es salvable; uno siempre puede escribir sus fachadas para las APIs complejas y olvidarse del problema (o usar las de otros; Spring en gran parte es eso).

Lo otro es el ecosistema. Sí, existen librerías y frameworks con graves excesos de ingeniería. Sí, Java EE no es la plataforma más sencilla del mundo. Pero eso no es un problema de Java- especialmente porque existen frameworks y librerías bien diseñados y con una complejidad adecuada. Java + Spring MVC no será la plataforma de desarrollo web más sencilla que existe, pero su complejidad está bien alineada con su potencia.

En resumen; sí, Java tiene sus defectos. Pero tiene muchos más “defectos ajenos” que propios. Y es preocupante la cantidad de detractores que no ven la viga en su propio ojo, o que critican con desconocimiento de causa. Yo ciertamente estoy contento de disponer de Java para ciertas tareas, tal como le veo muchos defectos y nunca lo usaría para todo.

¿Cuánto rato se tarda en montar un entorno de desarrollo web Java?

Una de las quejas más comunes sobre desarrollar en Java es lo complejo que resulta montarse el entorno de desarrollo. Ciertamente, la situación hace años era un poco rollo; grandes descargas del JDK perdido entre las tinieblas, Eclipse por piezas difícil de instalar…

¿Cuál es la situación actual? ¿Sigue siendo tan complejo? ¿Los anchos de banda más anchos de hoy en día ayudan?

Para el propósito de este ejercicio, cogeré un Windows sin nada instalado e instalaré todo lo necesario para poder desarrollar un servlet “Hola, Mundo”, con Eclipse (el entorno de desarrollo gráfico gratuito para Java más común).

Los pasos que deberemos realizar son los siguientes

  1. Ir a la página de Oracle, Downloads, Popular Downloads, Java for Developers, JDK, Aceptar la licencia y escoger la versión adecuada (en mi caso Windows x64)… 1 minuto
  2. Descargar los 92mb… 7 minutos
  3. Ejecutar el instalador… 3 minutos (+2 minutos de JavaFX que instala por defecto)
  4. Ir a la página de Eclipse, Download Eclipse, Eclipse IDE for Java EE Developers, escoger la versión adecuada (Windows 64 bits)… 1 minuto
  5. Descargar los 221mb… 16 minutos
  6. Abrir el .zip y extraerlo (en mi caso, a mi carpeta de usuario c:\users\alex, creándose una carpeta dentro c:\users\alex\eclipse)… 4 minutos
  7. Arrancar Eclipse (en mi caso c:\users\alex\eclipse\eclipse.exe),
    escoger la ubicación por defecto del workspace (y marcar que no vuelva a preguntar),
    crear un “dynamic web project”,
    escoger crear un nuevo runtime de Tomcat 7.0 (y darle una ruta, se lo baja y lo instala [unos 8mb]),
    decirle que nos genere un web.xml,
    hacer un click con el botón derecho y sobre la sección de servlets y decirle que nos cree uno, todo por defecto,
    implementar el método doGet haciendo un response.getOutputStream().print(“Hello world”);,
    hacer click derecho en el proyecto,  run as, run on server, hacer que corra en el Tomcat 7 que hemos creado anteriormente,
    editar la URL del navegador que se nos abra para que se corresponda a la ruta donde hemos mapeado el servlet y cargarlo
    … todo unos 7 minutos

En total, unos 40 minutos de los que unos 25 son unos 320mb de descargas. Lógicamente con una conexión más rápida (tengo una de 3 megabits) y sin la virtualización, que obviamente penaliza el rendimiento, podría reducirse un poco.

A destacar que el proceso tradicionalmente más complejo, instalar el Tomcat y configurarlo para que se pueda usar desde el Eclipse, ha sido simplificado por la gente de Eclipse haciendo que instalarlo y autoconfigurarlo directamente al crear un proyecto sea bastante sencillo (el interfaz no es 100% intuitivo y me ha costado un pelín entenderlo, pero bueno).

Por supuesto, este es un proceso mínimo usable; yo preferiría añadirle:

  • Instalación de egit, que sorprendentemente en la versión Java EE de Eclipse no viene cuando otras variantes de Eclipse lo traen por defecto (4 minutos de instalación desde Eclipse Marketplace, incluyendo un reinicio)
  • Instalación de m2eclipse y su plugin para WTP, que nos permite configurar proyectos usando Maven, un sistema bastante estándar de gestión de dependencias (6 minutos de instalación desde Eclipse Marketplace, con otro reinicio)

, y por supuesto, que esto nos instala un sistema de desarrollo “pelado” sin framework, cuando lo recomendable es no desarrollar servlets “a pelo” si no usar algún framework como Spring. Pero esto lo trataremos en otra entrega…

O sea, que podemos montar un entorno de desarrollo, con servidor de aplicaciones y entorno gráfico integrado en menos de una hora. ¿Es mucho, poco? ¿Cuánto se tarda con otras plataformas de desarrollo? ¿Es realmente un factor que eche para atrás de desarrollar con Java? ¿O son otros factores?

Maventuras

Los que me conozcan sabrán que éste es un momento de derrota. Tras casi 9 años participando en proyectos de desarrollo Java, hoy he commitado a Subversion un pom.xml.

La versión larga: voy a usar Maven profesionalmente.

¿Qué es Maven, a todo esto? (los no informáticos, ya deberíais haber apagado hace tres párrafos).

Maven es el estándar de facto para compilar (en moderno, hacer build-management) proyectos Java. Existe Ant (y otras cosas más modernas de las que hablaré más tarde), pero Ant es make, es una fantástica herramienta que puede hacer de todo, pero que por defecto, hace muy poco y, especialmente, no resuelve dos de las mayores pérdidas de tiempo en desarrollo Java:

  • Gestión de dependencias de terceros. Quieres usar Hibernate. Hibernate tiene como unas 15 dependencias directas, y algunas de esas dependencias tienen otras dependencias… resultado final, un ratito muy divertido descargando y colocando jars. Y, sobre todo, unas enormes ganas de actualizarse a versiones nuevas…
  • Dependencias entre proyectos. Uno quiere ser bueno y reusar código y modularizar. Poner las clases de utilidad que uno escribe siempre en un módulo que usen todos los proyectos. Hacer librerías de utilidad temáticas. Partir proyectos gordos en módulos separados. Pues bien, hacer un montaje que haga que el proyecto se pueda compilar automáticamente [pongamos con Ant] *y* que se integre propiamente en tu entorno [pongamos Eclipse], no es nada trivial. Queremos que al modificar una clase en un subproyecto, nos la cojan los proyectos de lo que depende. Esto, de hecho, es muy facilito de hacer en Eclipse… pero si quieres tener builds automáticos (pongamos, para hacer integración continua o barbaridades semejantes)… se complica el tema.

Los primeros en solucionar esto, fueron los sres. de Maven, con dos elementos:

  • Un sistema para describir proyectos *declarativo* (Ant es imperativo), que contempla especificar dependencias
  • Un repositorio de librerías Java que contiene todas las librerías relevantes, con sus dependencias especificadas

Con esto, yo puedo declarar que mi proyecto depende de Hibernate y Maven se descargará automágicamente todos los jars necesarios y los meterá en mi proyecto.  Esto ya sería suficiente, pero Maven ofrece más cosas:

  • Arquetipos.  Son una especie de plantillas de proyectos que te permiten crear proyectos típicos fácilmente (Eclipse ofrece algo similar, claro, pero Maven tiene más). Estos reducen, junto a la resolución de dependencias, permiten reducir bastante el coste de montar el esqueleto de un proyecto (nota: ¿más de lo que cuesta hacer funcionar Maven? No.). Estos arquetipos suelen estar bastante bien pensados (i.e. un arquetipo de proyecto web normalmente te generará un .war automáticamente, etc.).
  • Plugins. Todos esos programitas de unit testing, cobertura, análisis estático, etc. se ven traducidos en un plugin de Maven, que con añadirlo al descriptor del proyecto, ya se encarga de hacerlos funcionar casi automáticamente. Uno de estos plugins, por ejemplo, es el que te genera una mini-web de proyecto con documentación, javadocs, descargas, etc. que habréis visto mil veces si habéis visto webs de proyectos Java.

Yo hasta ahora había evitado usar Maven. La primera vez, porque estaban en un momento de transición (de Maven 1 a 2, si no recuerdo mal), había poca documentación, la integración con Eclipse no parecía muy boyante y, por qué no decirlo, bastante NIH. Acabé montando un sistema faraónico basado en Ant que si bien funcionaba como a mi me gustaba, era un poco pesado. Las veces siguientes, acabé reinventando mi pirámide, puliéndola a cada paso, pero haciéndola más complicada y aún no perfecta.

Y hasta hoy hemos llegado.  Se plantea la necesidad de compilar proyectos complejos. La diferencia esta vez es que hay menos libertad inventar cosas y poca voluntad de imponer el sistema a otros. Hora de jugar con Maven.

El primer descubrimiento, parece que hay plugin de Eclipse como Dios manda. Como siempre, hay un inconveniente. Si queremos integración con sistemas de control de versiones, tenemos que instalar los extras, y hay una pequeña nota en la web que dice:

M2Eclipse extensions are available from separate “extras” update site, see Installing m2eclipse for more details. Not all extensions are compatible with the latest M2Eclipse version.

Esto, lógicamente, hace que nos rompamos la cabeza hasta el infinito intentando instalar la compatibilidad con Subversive hasta leer este párrafo. La solución, instalar la versión 0.10.

Hasta ahora, poco más. El descubrimiento es que la manera Maven de gestionar multiproyectos pasa por tener un repositorio propio, cuando opino que no sería estrictamente necesario (al menos en mi caso particular), así que probablemente tendremos que añadir al coste de aprendizaje y montaje de Maven el montar un repositorio (los hay desde muy simples- una carpeta compartida, a auténticos mastodontes).

Para el futuro:

  • Ver si acierto pensando que el repositorio de Maven público es bastante caótico y problemático. Existe un repositorio de Maven de Springsource que tiene buena pinta, pero… ¿estará mucho mejor organizado? Probablemente, sí. ¿Estará todo lo que necesito allí? Probablemente no. ¿Será problemático mezclar el repositorio público y el de Spring? Seguramente.
  • Ver si la cosa funcionará como debe o si requerirá de cuidados.

JCR, Modeshape, programación web en general

Una cosa muy habitual requerida de un programador es realizar páginas web. La programación web, a un nivel muy alto, particularmente se preocupa de dos cosas:

  • Generar contenido- usualmente HTML– en respuesta a una petición HTTP para una URL. Es decir, cuando en nuestro navegador introducimos http://www.google.com, los servidores de Google nos responden con un HTML con la página de búsqueda de Google.
  • Procesar formularios. Tecleo la entrada de este blog en el interfaz de administración; cuando le doy a “Publicar”, los datos del formulario se envían al sistema de mi blog, que los procesa y los introduce en la base de datos del blog.

Hoy nos ocuparemos, en parte, de lo primero.

¿Cómo almacenamos el contenido de nuestra web?

Una primera aproximación sencilla es guardarlo en el sistema de archivos. Algo tan sencillo como guardar el HTML en carpetas del servidor funciona casi sin esfuerzo- simplemente le decimos a nuestro servidor web que para cada petición HTTP busque un fichero con la misma ruta y nombre que la petición y lo sirva al usuario.

Lógicamente, normalmente esto no es suficiente. Por ejemplo, no queremos repetirnos continuamente con la cabecera y pie de nuestra página web en cada HTML que creamos. Aquí, cosas tan sencillas como los server-side includes, el PHP o cualquier cosa con directiva “include” puede bastar.

Otro problema que plantea esta alternativa es su falta de versatilidad. Una evolución lógica (y popular) es guardar los contenidos en una base de datos, típicamente una que use SQL (básicamente, una base de datos relacional). Creamos un esquema de datos de la información que queremos mostrar en nuestra página (por ejemplo, entradas de blog, usuarios, categorías, etc.) y programamos una serie de páginas que, en función de la URL que nos piden, recupera la información de la base de datos y crea un HTML con esa información.

Esta mecánica es profundamente popular, y una parte muy significante de la web actual está implementada de esta manera.

Sin embargo, la opción más popular, las bases de datos SQL, no son apropiadas para todos los contenidos que queramos mostrar en una web. Las bases de datos suelen representar datos altamente estructurados, con esquemas rígidos (es decir, un usuario tiene un nombre, email; una entrada de blog tiene título, autor, fecha de modificación, cuerpo, etc.), y los sistemas de presentación web basados en bases de datos SQL suelen ser por consecuencia, rígidos. Esto en muchas ocasiones no es especialmente problemático, en otras es fastidioso pero soportable y en ocasiones, puede ser muy incómodo.

Lógicamente surgen alternativas a las bases de datos SQL; el movimiento NoSQL abandera a toda una serie de bases de datos no relacionales que se oponen a usar SQL. Normalmente, por motivos erróneos y en gran medida motivados por la existencia de MySQL, probablemente la menos relacional y SQLifica base de datos popular que existe.

Por mucho que uno opine que la mayoría de argumentos que esgrimen los defensores del NoSQL, uno sí piensa que pueden existir cosas mejores para almacenar contenidos para web. Una tecnología interesante en este sentido es Java Content Repository, un mecanismo de almacenaje de información muy adecuado para el contenido web. Unas cuantas características de los repositorios JCR son:

  • Jerárquico. Los contenidos (nodos) de JCR se organizan en una jerarquía, directamente identificable con la jerarquización típica de las URLs del contenido web
  • Versionado/con espacios de trabajo. Podemos almacenar todas las versiones que vayan habiendo del contenido, y disponer de varios espacios de trabajo paralelos (e.g. el espacio de trabajo público, un espacio de trabajo de borradores, etc.)
  • Con metadatos. Podemos almacenar metadatos sobre el contenido (autor, fecha de publicación, etc.) de una manera flexible

Así pues, en principio, JCR parece un sistema muy útil de cara a almacenar información web. Lo interesante de JCR es que es sólo una API, con varias implementaciones. Así, un repositorio JCR podría guardar su información en una base de datos SQL, en una NoSQL o en cualquier cosa que se le ocurre al implementador.

Y es aquí donde aparece Modeshape de JBoss. Modeshape es un JCR cuyo almacenaje es flexible. Más bien, JCR es una librería para implementar JCRs. Podemos implementar JCRs que cojan los datos de una base de datos, de otro JCR, de una fuente de datos NoSQL, de lo que sea. Y también nos permite unificar varios JCRs y acceder a ellos como si fueran uno.

Esto es harto interesante. Muchas aplicaciones web quieren recoger datos de diversas fuentes- algunas preexistentes y otras que se crean ad-hoc para la aplicación web en cuestión. Mediante Modeshape, podemos unificar el acceso a estas fuentes de dato, creando un adaptador a JCR que nos permita acceder a todos los datos que requerimos presentar vía web, mediante un mecanismo especialmente adecuado para su presentación web.

Para completar una aplicación web- o al menos su parte de presentación de contenidos, sólo necesitaríamos añadir algo que exponga el repositorio JCR que creamos a la web, lo cual sería algo interesante a comentar otro día.