Jul 13

Seguir las reglas a ciegas

Veo esta duda en StackOverflow en la que preguntan si hay alguna forma de que los getter y setter en java se puedan generar automáticamente desde código, igual que muestra cómo se hace en Javascript. Mirando las respuestas, se llega por ejemplo a proyectos como Project Lombok, en el que poniendo anotaciones @Getter y @Setter en el atributo, los genera automáticamente.

Si vamos un poco más allá, también el lenguaje Groovy hace automáticamente estas cosas, pone en los bytecodes compilados métodos getter y setter para los atributos, de forma que podemos usarlos desde otros lenguajes como java.

Maravilloso, todos sabemos que hacer los atributos privados y poner setter y getter es una de las buenas costumbres de programación y es pecado no hacerlo, así que todas estas maravillosas herramientas lo hacen AUTOMATICAMENTE por nosotros, ahorrándonos escribir el tedioso código.

Pero creo que nos olvidamos del fondo. ¿Por qué es bueno hacer los atributos privados y poner getter y setter?. La respuesta todos la sabemos: encapsulación. Pero, ¿nos hemos parado a pensar realmente qué es eso?

Imagina un atributo privado "chisme" con su correspondiente getter y setter

private double chisme;
public void setChisme(double chisme) {
   this.chisme=chisme;
}
public double getChisme() {
   return this.chisme;
}

La ventaja de la encapsulación es que si más adelante decido que en vez "chismes" tengo "trvilorios" (todos sabemos que los "chismes" y los "trivilorios" son equivalentes y podemos obtener unos de otros) y que en vez de double, es un BigDecimal, podemos hacer esto

private BigDecimal trivilorio;
public void setChisme(double chisme) {
   this.trivilorio = getTrivilorioAPartirDeChisme(chisme);
}
public double getChisme() {
   return getChismeAPartirDeTrivilorio(this.trivilorio);
}

Y esta es la verdadera ventaja, hemos cambiado el atributo, pero mantenemos los setter y getter de chisme, haciendo las cuentas necesarias en esos métodos. De esta forma, todo el código que use nuestra clase seguirá usando setChisme() y getChisme() y seguirá trabajando con chismes y no con tirvilorios, no necesitamos cambiar nada, posiblemente ni siquiera recompilar ese otro código,  y todo seguirá funcionando.

Pero si usamos maravillosas herramientas que generan automáticamente los getter y setter, perdemos el encapsulamiento, que es precisamente el único motivo de la existencia de esos setter y getter. En el momento que cambie "chisme" por "trivilorio", aparecerán automáticamente getTrivilorio() y setTrivilorio(), pero desaparecerán, también automáticamente, getChisme() y setChisme(), por lo que todo el código que hay por ahí usando setChisme() y getChisme() se debe rehacer, recompilar…. y posiblemente hacer las conversiones de chisme a trivilorio y viceversa, o bien tocar el código que usaba chismes y ahora tiene que usar trivilorios.

Así que ojo con estas herramientas. Si queremos que el código que usa nuestra clase no tenga que cambiar y usamos estas herramientas, después de cambiar chisme  por trivilorio, debemos escribir manualmente los métodos getChisme() y setChisme() con su correspondiente conversión, manteniendo así la compatibilidad y la encapsulación. Por supuesto, setTrivilorio() y getTrivilorio() pueden y deben añadirse, automática o manualmente.

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.