Java, editores colaborativos de código y compiladores en línea

¿Cuál es la mejor forma de ayudar a un novato que tiene problemas con un programa Java? agreguemos una par de características:

  • el novato está en otro lugar, físicamente alejado de donde te encuentras.
  • no queremos solicitar permisos “especiales” en la red que nos conecta a Internet.

Una de las primeras alternativas es utilizar medios como el correo electrónico o almacenamiento en la nube; es decir compartir el código fuente. Lamentablemente esta alternativa tiene algunas limitaciones como las siguientes:

  • quien revisa tiene muchas dificultades para leer el código, principalmente por que la herramienta utilizada no brinda las facilidades necesarias como por ejemplo: indentación o resaltado de sintaxis, por mencionar sólo un par. ¿Han leído código Java enviado en el texto de un email? o ¿a través de un mensaje de chat?
  • hay que usar mayor tiempo para encontrar los errores. Tal vez los errores de sintaxis sean los más obvios, pero los errores en la lógica del programa serán siempre los más completos.
  • imposibilidad de encontrar errores relacionados con el entorno de desarrollo. ¿Y si el error no está en el código? Tal vez el error se encuentre en una mal configuración del IDE que usamos, confusión entre JDK y JRE, etc., no olvidemos que usuario neófitos en programación.
  • complejidad para incluir explicaciones. Al no contar, con todas las facilidades que un IDE posee, como por ejemplo con números en cada una de las líneas del código, el indicar en donde están las fallas es un reto que exige que empleemos muchas más palabras. Ejemplo: la condición del if (el que tiene la siguiente forma if (a = 2) { .. ) no es correcta ya el operador de comparación es el ==.

Existen otras alternativas que se pueden emplear y que sin lugar a dudas ayudan en la búsqueda de respuesta a la pregunta plantea. Las he clasificado según su propósito en:

  • editor colaborativo de texto, es decir que permiten editar un documento simultáneamente por varios usuarios.
  • ide web, que permite editar, compilar y ejecutar programas, pero no el trabajo colaborativo.
  • ide web colaborativo, igual que el anterior con la diferencia que posee medios para realizar trabajo colaborativo.
  • emuladores de máquinas virtuales con interfaz web, aplicaciones que emulan a un sistema operativo y que poseen: mecanismos de administración de archivos, editores de código y terminal.

Finalmente por cada uno de las alternativas menciono al menos una aplicación, sus características vistas como ventajas y algunas desventajas que he podido encontrar. Ésta lista no es de ninguna manera ni completa ni está finalizada, sólo resumen un búsqueda que he realizado.

Nombre Tipo Ventajas Desventajas
TitanPad editor colaborativo de texto
  • No se necesita crear una cuenta para empezarlo a usar.
  • No es necesario compartir el documento (por defecto es público).
  • El editor posee líneas para cada una de las filas.
  • La sintaxis no se resalta y la indentación es opcional.
  • No existe opciones para compilar/ejecutar el código.
ideone.com ide web
  • No es necesario suscripción.
  • Resaltado de sintaxis.
  • Números en las líneas del editor.
  • Es posible descargar o copiar el código
  • Existe un mecanismo para el ingreso de datos.
  • Soporta más de 60 lenguajes de programación.
  • Se puede escribir comentarios, no directamente en el código sino al estilo post de un blog
  •  El mecanismo de ingreso de datos es poco intuitivo para alguien que recién está empezando.
  • No existe autocompletado de sintaxis.
  • Aparentemente no es posible trabajar con varias clases en diferentes archivos
codingground ide web
  • No es exclusivo para Java y soporta otros lenguajes.
  • No es necesario suscripción.
  • Resaltado de sintaxis.
  • Números en las líneas del editor.
  • Se puede compartir el proyecto.
  • Es posible trabajar con varias clases
  • Existe un terminal que parece ser bastante completo. Ejecuté comandos como ls, cd, java, javac, pwd, git clone.
  • Se puede clonar proyectos publicados en git.
  • Se puede guardar e importar proyectos desde varias fuentes: Git, Google Drive, DropBox, One Drive
  • Existen un conjunto de tutoriales que se puede seguir.
  • El proceso de compilación no toma en cuenta la ruta del archivo que muestra el editor, sino que usa el directorio del terminal. Es decir usando comando nos dirigimos hacia otro directorio y enviamos a compilar y obtendremos errores de archivo no encontrado.
  • No es existe mecanismo para recibir comentarios.
 coderpad ide web colaborativo
  • Soporta varios lenguajes de programación
  • Existe la posibilidad de iniciar un google Hang outs.
  • Resaltado de sintaxis.
  • Números en las líneas del editor.
  • Es posible compartir el editor.
  • Es de pago.
  • No se puede tener más de una clase.
  • Si queremos usar la demostración tenemos que tomar en cuenta que existe un control. Si terminas un trial y quieres volver a ingresar aparece un mensaje que te lo impide (control vía cookies)
codebunk ide web colaborativo
  • Soporta varios lenguajes de programación
  • Resaltado de sintaxis.
  • Números en las líneas del editor.
  • Es posible compartir el editor.
  • Es posible grabar un “vídeo” que muestra la construcción del programa.
  • Es de pago.
  • Las opciones colaborativas únicamente están disponibles una vez se realice el pago.
  • No es posible tener varias clases abiertas de forma simultánea.
  • El nombre de la clase no es editable.
 kobra  editor colaborativo de texto
  • Es posible transmitir audio y vídeo.
  • Soporta varios lenguajes de programación
  • Resaltado de sintaxis.
  • Números en las líneas del editor.
  •  Es de pago
  • Las opciones colaborativas están disponibles cuando se compre el servicio.
 cloud9 emulador de máquinas virtuales con interfaz web
  • Emula a un computador con Ubuntu.
  • Soporta Java a través de comandos por el terminal.
  • Posee un servidor Web para ejecutar aplicaciones Web.
  • Soporta varios lenguajes de programación
  • Resaltado de sintaxis.
  • Números en las líneas del editor.
  • Autocompletado de sintaxis mientras se escribe.
  • Integración con GitHub y Bibucket.
  • Varios opciones del IDE: Full, Minimal, tipo Sublime.
  • Posee sinippets de código, algo así como los shortcuts de Netbeans.
  • Es pago, aunque la versión gratuita tiene las prestaciones suficientes para alguien que empieza.
 koding  emulador de máquinas virtuales con interfaz web
  • Soporta varios lenguajes de programación
  • Resaltado de sintaxis.
  • Números en las líneas del editor.
  • Autocompletado de sintaxis mientras se escribe.
  • Posee sinippets de código, algo así como los shortcuts de Netbeans.
  • Posee un terminal bastante completo que permite integrarse con repositorios Git.
  • Vídeo chat (beta) para trabajo colaborativo.
  • Es pago, aunque la versión gratuita tiene las prestaciones suficientes para alguien que empieza (1 GB de RAM, 3GB de disco y 1CPu).

De seguro existen otras herramientas que aún no conozco, por eso este post aún no está cerrado. Otro tema pendiente son las pruebas de las características colaborativas, por ahora sólo hice pruebas con koding, veamos como me va en el mundo real, con estudiantes novatos.

Java Web Development – ¿Alguna novedad?

Desde hace algún tiempo venía buscando un framework Web ligero para Java. En ese proceso encontré algunos frameworks que quiero comentar.

Spark framework – A tiny Java Web framework

Aclaración, Spark framework no tiene relación alguna con Spark de Scala. El primero es un framework para crear aplicaciones Web, mientras que el segundo es para el procesamiento de BigData.

Link

Desde mi punto de vista, su principal característica es la simplicidad y su utilidad está en el desarrollo rápido de servicios REST para prototipos o educación, en cuestión de segundos puedes tener un API Web funcional sin mayor esfuerzo.

Como ya lo mencioné se puede usar en educación para una introducción rápida a REST y Java 8 (lambdas) ya que usa esa característica de Java. Algo de código:

import static spark.Spark.*;

public class HelloWorld {
    public static void main(String[] args) {
        get("/hello", (req, res) -> "Hello World");
    }
}

Y para ejecutarlo visitar: http://localhost:4567/hello

Vert.x

Link

Vertx es un framework diferente, completo y específico para tareas de alto desempeño muchos lo llegan a comparar con Node.js. Lo que me llamó la atención es su arquitectura, la forma de comunicación que emplea entre los componentes del lado del servidor, el uso de nuevos estándares como WebSockets y finalmente que es políglota se puede usar con Javascript, Java, Ruby, Groovy, Python, Clojure, Ceylon y pronto en Scala.


public class ApiServer extends Verticle {

   @Override
   public void start() {
      HttpServer server = vertx.createHttpServer();
      RouteMatcher routeMatcher = new RouteMatcher();

      routeMatcher.get("/users/", new Handler<HttpServerRequest>() {
         @Override
         public void handle(HttpServerRequest request) {
            request.response().putHeader("content-type", "text/plain");
            request.response().end(String.format("%s[%s]\n", request.path(), request.method()));
         }
      });
   }
}

Y para ejecutarlo se debe visitar: http://localhost:8080/users

Si bien los frameworks anteriores tienen su utilidad yo buscaba algo diferente, algo más orientado al desarrollo de clientes Web que por ejemplo maneje un sistema de Templates.

Ninja Web framework

Link

Completo para mis necesidades, simple, elegante y bastante potente. Desarrollé mi primera aplicación Ninja y me fue muy bien.

Este framework tiene muchas características y su propia filosofía, no existen sesiones manejadas en el servidor y el uso de un grupo de estándares Java perfectamente integrados que hace que el desarrollo sea rápido, orientado a las pruebas y extensible.

Para los relacionados con Scala, Ninja es algo así como un fork de Play y como leí en algún lado sigue en algo la filosofía de Rails de Ruby.

En resumen un framework Web orientado a acciones y no a componentes, que desde mi punto de vista es la tendencia.

Algo de código, así se manejan las rutas en Ninja:


public class Routes implements ApplicationRoutes {

@Inject
NinjaProperties ninjaProperties;

@Override
public void init(Router router) {

///////////////////////////////////////////////////////////////////////
// Login / Logout
///////////////////////////////////////////////////////////////////////
router.GET().route("/login").with(LoginLogoutController.class, "login");
router.POST().route("/login").with(LoginLogoutController.class, "loginPost");
router.GET().route("/logout").with(LoginLogoutController.class, "logout");

...

También existen otros frameworks:

Y poco tiempo después se anunció que la nueva versión de Java EE tendrá un nuevo framework MVC orientado a acciones (así como Ninja), detalles aquí.

Scrapping la Web con apache HTTPComponents y Jsoup

Siguiendo con el tema de recuperación de información desde páginas, se supondría que en esta entrada hable un poco más de jARVEST, pero se dieron algunos cambios que hicieron que cambie de herramienta.

Tengo varios millones de URLs a procesar y para acelerar su procesamiento utilizo varios cientos de hilos – Threads que permiten mejorar la velocidad de procesamiento de horas a minutos. Y aquí el problema con jARVEST cuando traté de usarlo con más de 25 hilos empecé a tener problemas de falta de espacio de memoria (concretamente Java heap space – OutOfMemoryError), me imagino que la causa es porque jARVEST usa JRuby, aunque no lo he confirmado.

Por lo anterior dejé de lado jARVEST, y pasé a utilizar Apache HTTPComponents, aunque ya lo había usado anteriormente, no lo había explotado en temas de scrapping. HTTPComponents es un API bastante potente que se puede convertir en compleja, pero que gracias a Fluent API, la tarea se convierte en sencilla.

El código básico que usé es el siguiente:

Request.Get("https://cafelojano.wordpress.com").
userAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.76.4 (KHTML, like Gecko) Version/7.0.4 Safari/537.76.4").
 connectTimeout(10 * 1000).
 socketTimeout(15 * 1000).
 execute().returnContent().asString();

El código anterior recupera el código HTML de la página principal de este blog. De aquí comentar únicamente los métodos connectTimeout y socketTimeout que según ésta página, el primero determina el tiempo que se esperará a que el servidor responda, mientras que el segundo determina el tiempo de espera entre flujos de datos.

La mejor noticia es que con la configuración anterior, aquel link que me devolvía una página de login, ahora si me devuelve la misma página que cualquier navegador.

El siguiente paso es utilizar Jsoup para encontrar todas los metadatos que son de nuestro interés. El siguiente código lo utilicé para obtener las metatags (todas las etiquetas que empiezan con la palabra meta). Utilizo un Map para almacenar los metatags de la página, aunque este código únicamente permite obtener el último valor de la metatag, en el caso de que una misma metatag se use varias veces (dentro de la misma página, esto es posible).


Map<String, String> output = new HashMap<String, String>();
Elements metaElements = doc.select("meta");
String name = "";
String content = "";
Attributes atts;

for (Element ele : metaElements) {
   atts = ele.attributes();
   if (atts.size() > 1) {
      for (Attribute att : atts) {
         if (att.getKey().equalsIgnoreCase("content")) {
            content = att.getValue();
         } else {
            name = att.getValue();
         }
      }
   } else {
      Attribute att = atts.asList().get(0);
      name = att.getKey();
      content = att.getValue();
   }
   output.put(name.trim().toLowerCase(), content.trim());
}

En una prueba se analizó 13455 links y aquí está el top ten de los metadatos más utilizados:

Metatag Cantidad
description 9588
content-type 6556
og:url 6368
og:image 6324
og:title 6251
og:type 6245
og:description 6010
og:site_name 5809
charset 5303
viewport 4399

Como se puede ver en la tabla anterior cerca del 50% de las páginas analizadas usan Facebook Open Graph, mientras que recién en la posición 12 aparece Twitter con 4229 páginas usando twitter:card.

Pero en resumen qué hacen éstas metatags de open graph, básicamente permiten que las URLs que publicamos en Facebook aparezcan con una imagen (og:image), un título (og:title) y una descripción (og:description), así como en la siguiente imagen

Open graph, un ejemplo práctico

Un ejemplo del uso de open graph

En las próximas entradas les seguiré mostrando la implementación completa, para ver el trabajo con hilos.

Scrapping la Web con Java – Jsoup y jARVEST

Una de las tareas en las que he trabajado últimamente es recuperar información de links URLs, principalmente información que se encuentra publicada en forma de anotaciones que dentro del HTML se expresan a través de Metatags. Básicamente estoy interesado en recuperar el título de la página Web (claro que no es una metatag) y las meta “description” y “keywords“.

Hasta el momento he trabajado con Jsoup y he tenido muy buenos resultados, Jsoup es una framework que permite representar a una página HTML, que se puede leer desde una url, una variable o un archivo, como un objeto y a través de algunos métodos manipular el DOM. Otra de las características que destaco la manera de seleccionar los elementos del DOM, que es similar a jQuery.

Estas son las líneas de código que utilizo para leer una página Web desde una URL:


Document doc = Jsoup.connect(urlHome).
userAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.76.4  (KHTML, like Gecko) Version/7.0.4 Safari/537.76.4").
timeout(10 * 1000).
ignoreContentType(true).
ignoreHttpErrors(true).
followRedirects(true).
get();

Mencionar el método userAgent que le dice al servidor Web quién hace la llamada, uso el de Safari para “tratar” de converser al servidor Web que es una persona que quiere ver la página y no un programa que esta haciendo scrap. Otros métodos que mencionaré son ignoreContentType e ignoreHttpErrors, estos métodos ayudan a que no se lancen excepciones cuando la URL a visitar, no apunta a una página HTML sino a un archivo con extensión diferente a html, y que en lugar de lanzar una excepción cuando existen errores HTTP 4xx o 5xx, este error se convierta en un objeto.

Para obtener las meta, utilicé el siguiente código:


doc.title();

Elements metaElements = doc.select("meta[name]");

Así puedo obtener el título y todas las meta que tienen la propiedad name, para luego trabajar en las que son de mi interés.

Luego de hacer scrapping a varios miles de páginas, me di cuenta que muchas de ellas no poseían, ni la etiqueta title ni las meta description o keywords y que en muchos casos preferían utilizar anotaciones de Facebook Open Graph o de Twitter Cards. Así que modifiqué el código para que también seleccione estas meta y quedando así:

doc.title();

Elements metaElements = doc.select("meta[name]");
Elements others = doc.select("meta[property]");

Con esto se mejoró notablemente la recuperación de la información, pero aún quedaban algunas URL con un comportamiento extraño, por ejemplo esta: Can Emotional Intelligence Be Taught? que cuando se la abre desde cualquier navegador funciona sin problema, pero cuando la proceso con Jsoup me aparece una página de login.

El problema parece ser que ese sitio Web, recibe la solicitud, escribe algunas cookies y envía una página de redirección, recibe la segunda página y busca las cookies escritas previamente, esto es normal en navegador Web, pero no en Jsoup busqué la forma de arreglarlo, pero no tuve éxito.

Es así que recordé otro framework que permite hacer scrapping que se llama jARVEST. Estudiando la escasa documentación pude comprender el potencial de la herramienta. Mi primera prueba fue cargar el contenido de la página de ejemplo y usar Jsoup para hacer el scrap, así:

Document doc;
String url = "http://www.nytimes.com/2013/09/15/magazine/can-emotional-intelligence-be-taught.html?_r=1&";
Jarvest scrapper;
String html;

scrapper = new Jarvest();
html = scrapper.exec("wget",url)[0];

doc = Jsoup.parse(html);

System.out.println(doc.title());

Y así pude ver que ya no se devolvía el título de la página de login, sino el mismo título que muestra el navegador. El problema real con jARVEST es la falta de documentación, estuve buscando un par de días y no pude encontrar ni la Javadoc. Pero con varios intentos prueba/error pude construir este “transformador” para obtener los mismos datos que con Jsoup. Este código se puede ejecutar desde una ventana terminal.


echo "http://www.nytimes.com/2013/09/15/magazine/can-emotional-intelligence-be-taught.html?_r=1&" | ./jarvest.sh run -p "wget
branch(:BRANCH_DUPLICATED, :ORDERED){ 
 pipe{
 xpath('//title')
 }
 branch(:BRANCH_DUPLICATED, :SCATTERED){
 select(:selector=>'meta[name]', :attribute=>'name')
 select(:selector=>'meta[name]', :attribute=>'content')
 }
 branch(:BRANCH_DUPLICATED, :SCATTERED){
 select(:selector=>'meta[property]', :attribute=>'name')
 select(:selector=>'meta[property]', :attribute=>'content') 
 }
}"

En una siguiente entrada hablaré un poco más de jARVEST, su potencial y lo que he aprendido, ya que veo un potencial bastante grande en esta herramienta.

JPA – Improve performance

En estos días tuve una tarea relativamente sencilla que en resumen consistía pasar los datos de una tabla hacia otra, previo algunos procesos de transformación y cambio (esto lo hice invocando código dinámicamente, luego se los comento); así ya se pueden dar una idea de lo que debía hacer, lo que debo destacar aquí es el volumen de datos ya tenía 1450000 filas aproximadamente.

Lo que utilicé para la tarea fue JDK1.8, JPA como base de datos MySQL. Como se pueden imaginar la tarea es bastante sencilla un par de entidades JPA que representan las tablas origen y destino, y lo único que queda es ejecutar las transformaciones. El verdadero problema llegó cuando traté de ejecutar el proceso sobre todo el conjunto de datos. Llegué a procesar 100000 registros en 230 minutos, ese resultado era intolerable.

La tarea se convirtió en mejorar el desempeño de JPA, luego de buscar encontré está página este blog  Java Persistence Performance – How to improve JPA performance by 1,825% y traté de implementar algunas de las recomendaciones que ahí se hacen. En resumen implementé las siguientes (la paginación ya la tenía):

  1. Batch writing, optimización número 8. Agregué las siguientes líneas a mi persistence.xml:
    <property name="eclipselink.jdbc.batch-writing" value="JDBC"/>
    <property name="eclipselink.jdbc.batch-writing.size" value="1000" />
  2. Implementé también la optimización 11, agregando las siguientes líneas al mismo archivo
    <property name="eclipselink.persistence-context.flush-mode" value="commit"/>
    <property name="eclipselink.persistence-context.close-on-commit" value="true"/>
    <property name="eclipselink.persistence-context.persist-on-commit" value="false"/>

    No me quise eliminar los mensajes de log.

  3. Finalmente agregué un parámetro al url de mi conexión, quedando así
    <property name="javax.persistence.jdbc.url" value="jdbc:mysql://<myserver>:<myport>/<mydatabase>?rewriteBatchedStatements=true"/>

    Esto lo encontré en el mismo blog, pero la entrada Batch Writing, and Dynamic vs Parametrized SQL, how well does your database perform?

Con éstas configuraciones logré procesar el 1450000 registros en 19 minutos, no cambié nada en el código únicamente modifiqué el archivo de configuración de JPA.

Espero que éstas líneas les puedan ayudar a ustedes también.

RDF y sus formatos

Dentro de la Web Semántica, existen muchas formas de “serializar” la información que está expresada en RDF y gracias al Jena esta es una tarea bastante sencilla, usando ResultSetFormater (para consultas ASK y SELECT) y el método write de la clase Model (para CONSTRUCT y DESCRIBE).

Algunas veces me he encontrado con la necesidad de trabajar con los tipos mime de estos formatos, es por eso que elaboro esta tabla que muestra el formato rdf y sus respectivos tipos mime, y alguna información adicional.

Formato Tipo MIME Jena writer Extensiones
Turtle (descripción) text/turtle TURTLE, TTL, Turtle .ttl
N-Triple (descripción) application/n-triples N-TRIPLES, N-TRIPLE .nt
RDF/XML (descripción) application/rdf+xml RDF/XML .rdf
N3 (descripción) text/n3 N3 .n3
JSON-LD (descripción) application/ld+json JSON-LD .jsonld
JSON (descripción) application/json
  1.  RDF/JSON *
  2. Serializing SPARQL Query Results in JSON **
.json

* RDF/JSON nos permite obtener resultados así: http://dbpedia.org/data/Ecuador.json

** Este formato es un estándar definido por la W3C y que es diferente a RDF/JSON y que se obtiene cuando se hace consultas SELECT SPARQL y se fija el formato en JSON.