Mar 29

He leído “JavaScript, The Definitive Guide”

Hace un mes aproximadamente terminé de leer "JavaScript, The Definitive Guide". Un libro sobre JavaScript y alrededores que me ha encantado. Aparte de JavaScript, trata bastante bien temas como JavaScript en un navegador web, una introducción a node.js y rhino en el lado del servidor, AJAX, jQuery, almacenamiento local en el navegador, Canvas de HTML5, …

Son un montón de páginas, 1100 nada menos, pero aproximadamente la segunda mitad son una guía de referencia de las funciones de JavaScript, por lo que de lectura es aproximadamente la mitad.

Comienza con los principios de programación en JavaScript desde cero, el típica capítulo de introducción al lenguaje que no aporta demasiado a casi nadie, demasiado rápido para el que no sabe nada de programación, pero demasiado trivial para el que sabe programar en otros lenguajes. Aun así, dentro de esta parte, he encontrado una pequeña joya para alguien como yo acostumbrado a otros lenguajes y es todo el tema de cómo se hacen conversiones de tipos automáticas, sobre todo en los condicionales, es decir, cuándo una variable independientemente de su tipo (string, numérico, un objeto,…) se considera que es true o false.

Sin embargo, luego empieza a meterse en profundidad en montones de temas variados de JavaScript y aquí es donde algún programador experto en otro lenguaje pero sin demasiado conocimiento de JavaScript, empieza a disfrutar del libro. Por supuesto, hay temas demasiado farragosos como para que sea agradable leerlos, pero hay otros que me han parecido geniales, tanto por lo que supone aprender cosas que no sabes, como por la forma de exponerlas.

Entre los primeros, los farragosos, está la parte de orientación a objetos en JavaScript, clases, herencias, polimorfismo a base de tipado tipo pato, También la parte de eventos en los navegadores web es pesadita, más que nada porque cada navegador es de su padre y de su madre y no hay acuerdo en los eventos que se producen, cómo se llaman y cuándo se producen. El libro no puede hacer mucho más que dar una lista con una breve descricpción de cada uno de ellos.

Sin embargo, entre las partes geniales, me ha encantado la forma de explicar las expresiones regulares, tanto, que he hecho mi propio tutorial de expresiones regulares en JavaScript siguiendo esa forma de explicación, por supuesto, donde esté el libro que se quite cualquier tontería que haya podido hacer yo. También me ha encantado la forma de explicar jQuery, todos sus apartados, desde los selectores para buscar y modificar elementos de nuestro HTML, como la parte de AJAX, efectos especiales como fadeIn() y fadeOut(), …

En fin, totalmente recomendado para aquel que ya ha empezado a programar cosas en JavaScript pero necesita profundizar y comprender más el tema.

Jan 09

“Duck Typing”

En un lenguaje fuertemente tipado y orientado a objetos, se comprueban las clases de los objetos antes de asignarlos a variables, de forma que sólo se pueden asignar a una variable objetos que son de la misma clase que la variable o hijas de la misma. Por ejemplo, si la clase Hija herada de la clase Padre, se puede hacer esto

Padre p = new Hija();

Una vez hecho, sólo pueden llamarse a métodos o atributos que estén declarados en la clase Padre. Si Padre tiene metodo1() e hija tiene metodo2(), sólo podemos hacer p.metodo1(), mientras que p.metodo2() dará error. Todo esto da sentido a cosas como las interfaces, definiendo a priori que métodos necesitan tener las clases hijas para que luego estas lo implementen.

Hay otros lenguajes, como javascript, que usan lo que se llama "Duck typing" o como lo traduzco yo "tipado tipo pato". La idea básica de este tipado es que si algo anda como un pato, grazna como un pato y nada como un pato, pues entonces es un pato. Los lenguajes que usan este tipado no miran los tipos ni las herencias de los objetos, simplemente permiten asignar cualquier cosa a cualquier variable. De esta forma, podemos hacer

p = new Hija();

y luego llamar tranquilamente a p.metodo1() o p.metodo2(), pero también podemos hacer

p = new Padre();

y llamar a p.metodo1(), dando error p.metodo2(). Es decir, no importa el tipo, el error saltará a la hora de hacer la llamada si "el pato no es capaz de granzar".

 

Mar 16

google-gson para manejar json desde java

jsongoogle-gson es una pequeña librería java que nos permite convertir una clase java en un String con formato JSON y viceversa. Es útil si hacemos una aplicación web con java en el lado del servidor y usamos el formato JSON para enviar y recibir datos al navegador.

Un pequeño ejemplo, hagamos un par de clases java sencillitas, dos bean sin necesidad de métodos set y get, pero con un constructor sin parámetros. Una de ellas tiene como atributo, entre otros, a la otra clase.

class Dato {
   private double numero;
   private int array[];
   private String texto;
   private LinkedList<Boolean> lista;
   private DatoInterno dato;

   public String toString() {
      return texto + " " + numero + " " + Arrays.toString(array) + " "
        + Arrays.toString(lista.toArray()) + " " + dato;
   }
}

class DatoInterno {
   private float valor;

   public String toString() {
      return "" + valor;
   }
}
 

Le hemos puesto unos métodos toString() para ver por pantalla fácilmente su contenido

Una vez instalada la librería en nuestro proyecto (es un solo jar), podemos hacer un código como este

Gson gson = new Gson();

Dato dato = gson.fromJson("{numero:1.4,texto:dos,array:[1,2,3,4],lista:[true,false],dato:{valor:11.22}}",
        Dato.class);
System.out.println(dato.toString());

 

que da de resultado algo como esto

dos 1.4 [1, 2, 3, 4] [true, false] 11.22

es decir, la salida de nuestro System.out.println() en el que hemos obtenido una clase dato rellena con los datos del texto json. Por otro lado, también tenemos la posibilidad inversa. Si una vez relleno el dato llamamos a

System.out.println(gson.toJson(dato));

obtendremos la siguiente salida

{"numero":1.4,"array":[1,2,3,4],"texto":"dos","lista":[true,false],"dato":{"valor":11.22}}

es decir, el texto JSON correspondiente a lo que tenemos dentro del dato, pero perfectamente formateado y no la "guarrería" que había puesto yo inicialmente en el código.

En fin, sencilla de usar y bastante potente.

 

Jan 17

Constantes en los beans y JSTL

A veces, en una aplicación web con JSTL nos vendría bien tener una constante definida en uno de los beans de java, estilo

public class UnaClase {
   public static final String UNA_CONSTANTE = "algo";
   …
}

y luego poder llamarla desde JSTL con algo como

<jsp:useBean id="bean" class="com.chuidiang.UnaClase"></jsp:useBean>

<c:out value="${bean.UNA_CONSTANTE}" />

Desgraciadamente, eso no funciona. JSTL presupone que UNA_CONSTANTE es un atributo del bean y va a convertir ese ${bean.UNA_CONSTANTE} en una llamada al método bean.getUNA_CONSTANTE() que no existe.

La solución es fácil, basta con crear un método getUNA_CONSTANTE() en el bean que devuelva el valor de la constante. Unicamente tenemos que tener en cuenta que ese método no puede ser static, puesto que si no JSTL tampoco lo llamará (por debajo, probablemente usa la introspección de java y no busca métodos estáticos). El bean quedaría así

public class UnaClase {
   public static final String UNA_CONSTANTE = "algo";

   public String getUNA_CONSTANTE () {
      return UnaClase.UNA_CONSTANTE;
   }

}

que sí funciona como esperamos.

Jan 14

El WebappClassLoader y ContextClassLoader en Tomcat/Liferay

En el desarrollo nos hemos encontrado con un problema curioso. Estamos desarrollando un portlet con Liferay y necesitamos desde él hacer llamadas AJAX que actualicen parte del portlet sin refrescar la página. Se nos ha ocurrido, en la parte del servidor, hacer un jsp que sería el que reciba estas llamadas desde la parte de javascript, digamos un funcion.jsp. En esa funcion.jsp usamos clases de nuestra parte del servidor del portlet, en concreto, usamos los jar que hay en el WEB-INF/lib de ese portlet.

Pues bien, el problema que se nos ha presentado es que aunque todo parece ir bien tanto en el funcion.jsp como en las clases que se van llamando, hay un sitio concreto en el que hay un problema. Esas clases crean un cliente de web service con Apache CXF para conseguir datos en otros servidores y en la creación de ese cliente nos salta el problema, una excepción fea

ClassCastException: com.sun.xml.ws.client.sei.SEIStub cannot be cast to org.apache.cxf.frontend.ClientProxy [java] at org.apache.cxf.frontend.ClientProxy.

A poco que se hurge con google, encontramos que la versión 6 de java viene con un proveedor por defecto para web services. Java proporciona mecanismos para cambiar ese proveedor por defecto por el que queramos, en concreto y entre otras opciones, basta con poner en el classpath el fichero META-INF/services/javax.xml.ws.spi con una única línea de texto que sería la clase proveedor de web service que queramos uar,  en mi caso, la de apache cxf. La excepción surge si cuando java busca el proveedor no lo encuentra, poniendo entonces el suyo por defecto, que no es compatible con Apache CXF.

Normalmente no debemos preocuparnos de esto, el jar cxf-rt-frontend-jaxws.jar de apache cxf contiene ese fichero debidamente configurado, por lo que si este jar está en el classpath, no debería haber problemas.

¿Por qué entonces surge el problema cuando llamo al funcion.jsp si este jar está en el WEB-INF/lib?. Pues tras varios días de pruebas, google y más pruebas, encontramos que nuestras clases usan por defecto el WebappClassLoader que les proporciona tomcat, por lo que todos los jar en WEB-INF/lib de nuestro portlet están disponibles, pero java, cuando busca el proveedor de servicios, usa Thread.currentThread().getContextClassLoader() que NO le devuelve el WebappClassLoader, sino el de la propia aplicación de Tomcat, por lo que las clases de nuestra aplicación no están disponibles.

Si experimentamos y hurgamos un poco más, vemos que Tomcat, cuando va a llamar a algo de nuestra aplicación web, nos cambia ese ContextClassLoader haciendo algo como

Thread.currentThread.setContextClassLoader(elWebappContextClassLoaderCorrespondiente);

y luego, cuando nuestra aplicación termina de hacer lo que tenga que hacer, Tomcat restaura el ContextClassLoader por el de defecto.

El problema que tenemos entonces es que cuando se llama a nuestra funcion.jsp, no se está cambiando ese ClassLoader. Ahora, sabiendo el problema, la solución debería ser fácil.

La primera y más inmediata es que nosotros mismos, antes de crear el cliente web service, cambiamos ese ContextClassLoader y luego lo restauramos, algo similar a lo que hace Tomcat. Esta opción no me gusta porque no me gusta jugar con los ClassLoader sin saber a ciencia cierta qué hago, y sobre todo porque Tomcat debería cambiarnos el ClassLoader y no lo hace, lo que implica que algo tenemos mal configurado.

Como estamos con liferay y llamamos a funcion.jsp con una URL directa, no a través del portlet liferay, imagino que ahí vienen los problemas. Así que toca "investigar" un poco a ver cómo conseguir que liferay/tomcat consideren funcion.jsp como parte del webapp o portlet y le cambien el classloader al Thread dichoso.

 

Dec 15

Clases y herencia con javascript

 Por la necesidad de organizar un poco el código de javascript, que va creciendo y creciendo de forma desordenada y desmesurada en nuestro proyecto, me he puesto a mirar un poco el tema de objetos y herencias, también como organizar esas clases en lo que en java se llaman paquetes, no sé si en javascript se llaman namespaces, o ni siquiera existe nombre para eso.

Me ha llamado la atención que las clases realmente son las funciones. Cualquier función que declaremos en javascript es una clase y se puede hacer un new de ella. La función en sí misma se convierte en el constructor de la clase y las "cosas" que definamos en esa función como this.cosa=…. se convierte en atributo o método de esa clase, según sea una variable u otra función.

La herencia es un poco rara, sobre todo cuando buscamos en internet en que hay 49 formas de hacerla y alguna más. Al final, lo más sencillo y mínimo imprescindible es hacer algo como ClaseHija.prototype = new ClasePadre; Ya está la herencia hecha.

Si el constructor Padre tiene parámetros (la función Padre tiene parámetros), podemos llamarla desde el constructor del Hijo (la función Hijo) usando call() tal que así Padre.call(this,parametros), esa sería la forma de que el constructor hijo llame al padre pasándole cosas.

Finalmente, para agrupar las clases en "paquetes" o como quiera que se llame en javascript, basta con hacer el típico 

paquete = {
   Padre : function(…) {….},
   Hijo : function(…) {…}
}

a = new paquete.Hijo;

En fin, lenguaje demoníaco por un lado, pero me está gustando por otro. Mas detalles de lo aprendido en la chuwiki.

Nov 26

Abrir conexiones java contra un servidor https

Me ha tocado abrir conexiones desde código java contra  un servidor https que requiere certificado de cliente. Me he puesto a ello y he aprendido algunas cosas.

Cuando hacemos un cliente java contra un servidor https, java verifica que el certificado que presenta ese servidor es válido. Por ello, si no los tenemos, necesitamos obtener dichos certificados y meterlos en un almacén de certificados que luego le diremos a java que es el almacén de certificados en los que confiamos. Una forma de obtener el certificado es visitar la página con el navegador y pinchar el el candadito que sale junto a la URL. Ahí podemos ver los datos del certificado y guardarlo en un fichero.

Con la herramienta keytool que viene con java podemos meter esos certificados en un fichero único, de nombre genérico "KeyStore". De hecho, el fichero por defecto que crea/usa esta herramienta keytool suele ser $HOME/.keystore. La herramienta keytool nos pedirá una clave cuando cree el fichero para protegerlo y nos pedirá la misma clave cada vez que queramos ver, añadir o borrar certificados de ese fichero. El formato de este fichero se conoce como "JKS" y es propio de java.

El certificado de cliente habitualmente nos lo darán como un fichero, protegido por una clave y su formato suele ser "PKCS12", este es un formato estándar entendido por la mayoría de las aplicaciones no java. Su extensión suele ser .p12

Pues bien, en java tenemos dos opciones para indicar cual es nuestro KeyStore y cual es nuestro certificado de cliente. Una es por medio de propiedades de sistema. Podemos arrancar nuestro código java con propiedades de este estilo

java -Djavax.net.ssl.trustStore=c:/usuario/.keystore ….

y necesitamos hasta 6 de estas propiedades: fichero, clave del fichero y formato del fichero, para el KeyStore y para el certificado del cliente.

Y la otra opción es codificarlo en java directamente, usando clases como SSLContext, TrustStoreFactory, etc, etc. Algo más complejo, pero que nos dará más versatilidad si queremos abrir varias conexiones con juegos de certificados distintos.

Cómo no, todo esto con más detalle en la chuwiki.

 

Sep 20

jax-ws, metro y cxf

No hace mucho que empecé a trabajar con web services. Buscando, buscando, vi como opciones axis y jax-ws. Al final, por sencillez, me decidí por jax-ws … pero hoy he descubierto un pequeño detalle que no sabía.

jax-ws no es más que una especificación y hay varias posibles implementaciones. Las más conocidas son metro y cxf. Yo he estado usando metro, confundiéndolo con jax-ws. Ahora que he descubierto que hay dos, he investigado un poco en internet a ver ventajas de una y otra. No he hecho pruebas ni una búsqueda exhaustiva, simplemente comento aquí algunas cosas que he visto.

Por un lado, metro obliga a poner las anotaciones sobre clases, mientras que cxf admite que se pongan en interfaces. No es algo demasiado importante, pero siempre es más elegante tener definido el web service sobre una interfaz.

Metro sólo soporta SOAP, mientras que cxf soporta también otros protocolos. De hecho, una misma interfaz puede llevar simultáneamente anotaciones de SOAP y de REST, de forma que la clase que lo implementa no necesita saber qué tipo de web service habrá detrás.Por su parte, Metro no soporta REST. La implementación de esta gente para REST está en un proyecto separado, Jersey.

Tanto Metro como CXF tienen plugin de maven para generar el WSDL a partir de la clase java o para generar las clases java a partir del WSDL.

Una cosa que he leído pero no he acabado de entender es que parece ser que hay diferencias a la hora de tratar/generar código en los parámetros de un WebMethod si estos parámetros tienen cierta complejidad, como ser colecciones. Intentaré echarle un ojo con más calma a ver.

Jun 21

JPcap vs JNetPcap

No hace mucho comentaba que me había puesto a partir paquetes IP a bajo nivel, usando JPcap. Haciéndolo encontré un pequeño bug en la librería, el campo offset de la cabecera IP no se rellenaba correctamente, por lo que tuve que hacerme mi pequeño arreglo. Una vez hecho, todos felices y contentos.

Pero me ha salido un nuevo problema. Cuando el sistema operativo recibe los fragmentos IP de un paquete grande, tiene un pequeño timeout en el que espera recibir todos esos paquetes (creo que de 1 minuto aproximadamente). Si en 1 minuto no recibe todos los fragmentos, desecha el paquete y no lo entrega a las aplicaciones. En windows ese timeout se controla ¿cómo no?, con un valor del registro, en concreto IpReassemblyTimeout. Pero mira tú que 1 minuto me resulta escaso (tenemos un canal de comunicación muy lento, casi como un antiguo RS-232 de 9600 baudios y encima compartido) y no todas las versiones de windows hacen caso de ese valor de registro (casualmente la que nosotros usamos no lo hace).

Así que me toca reconstruir también los fragmentos con JPcap. Y me pongo a ello…. y encuentro un nuevo bug. Hay un flag en la cabecera IP que indica si ese fragmento es el último o hay más. Pues bien, JPcap no rellena bien en recepción ese flag ni los otros dos flags que le acompañan. Poniendo el arreglo del enlace ya se arregla el tema de los flags. Pero me sale un nuevo problema … no recibo el último fragmento … hasta que  llega un mensaje. Es como si JPcap se quedara el último paquete recibido y no lo entregara a la aplicación hasta que reciba uno nuevo. No sé si es eso, pero el caso es que si sólo envio un gran paquete UDP fragmentado, no recibo el último fragmento y no puedo recomponer el paquete UDP.

Así que me pongo a buscar alternativas a JPcap y me encuentro con JNetPcap. Con esta librería sólo he probado la reconstrucción de paquetes, pero me ha funcionado bien a la primera (o casi). La librería es un pelín más compleja de usar que JPcap, pero viene bastante mejor documentada en su página web, con más ejemplos y lo más importante, parece que funciona mejor.

De momento no voy a migrar el envío de fragmentos, pero creo que sí voy a reconstruirlos con esta librería, afortunadamente, ambas son compatibles y una misma aplicación puede usarlas simultáneamente.

May 20

Y finalmente, haciendo un servidor de chat (III)

Al final no conseguí resolver totalmente los problemas de conexiones de mi cliente de chat. En ocasiones, sin saber muy bien el motivo, al entrar en la página web la conexión no se establecía. Y al dejar la página, google chrome capturaba bien el evento onUnload y desconectaba correctamente, pero internet explorer hacía cosas raras. Aparentemente capturaba el evento y mandaba la desconexión… pero el servidor openfire mantenía la conexión durante un minuto más. En ese tiempo, si intentaba reconectarme con el mismo navegador pero otro usuario, tenía el problema asegurado. Leí en algún sitio que internet explorer abre conexiones permanentes de justo 1 minuto de time out. Suficiente coincidencia como para pensar que mis problemas pueden ir por ahí.

Así que decidí dejar de pelearme con ello (casi una semana) y hacerme yo mismo mi servidor de Chat (sencillo y a medida) usando GWT. De paso paso aprendería a hacer la parte del servidor desde GWT y reaprovecharía el cliente de Chat que ya tenía en GWT, quitando las conexiones con jaxmpp2.

Dicho y hecho, en cuestión de una mañana tenía mi propio chat (sencillo y a medida) funcionando. Me queda pendiente revisar el tema del polling. Ahora mismo mi cliente pregunta una vez por segundo al servidor si hay mensajes nuevos que mostrar. Este mecanismo ya no se usa en los chats porque no es eficiente. En mi caso puede valer porque es un chat limitado a 10 ó 15 usuarios máximo.

Actualmente, en los chats se utiliza algo que se llama BOSH. Básicamente consiste en que el cliente pide datos al servidor y el servidor le deja bloqueada la llamada hasta que haya datos disponibles. Si pasado un tiempo (unos minutos), no hay datos disponibles, salta un timeout que el mismo cliente captura para volver a hacer la petición y quedarse colgado otra vez en espera de datos. Esto no deja de ser un polling, pero con mucho menos tráfico, ya que no es como en mi caso cada segundo, sino que de alguna forma es cada vez que salta el timeout (minutos) o cuando realmente hay datos.

También obliga a abrir dos conexiones. El cliente abre la que hemos comentado para pedir novedades, y abre una segunda cada vez que quiera enviar algo al servidor. En el caso del chat, sería para enviar un texto que ha escrito el usuario o la desconexión. El servidor no devolverá nada en estas peticiones, pero sí lo hará a través de la otra conexión, la de consulta.

GWT lleva algo "raro" parecido a eso, ya que de alguna forma el cliente pide datos pero recupera el control inmediatamente. El resultado le llega a través de un evento que provoca GWT. No he mirado con detalle el mecanismo que hay por debajo y por tanto no lo tengo claro del todo, pero lo apunto para investigar y ver si puedo hacer algo parecido al mecanismo BOSH con GWT.

Y también me gustaría repetir el ciente chat con una librería javascript reconocida (jaxmpp2 para gwt me parece un poco caótica y no sé si se usa mucho), para ver realmente el tema de conexiones y desconexiones con un servidor xmpp de verdad (openfire o ejabberd).