blog de ezamudio

Web Services en Axis2 con Spring y Gradle

Recientemente en un proyecto un cliente nos dijo que la interfaz entre nuestros sistemas sería... esperen... sí... un web service. Un web service que ellos invocarían y que por lo tanto nosotros tenemos que implementar. Así que nos dieron un par de archivos WSDL y unos ejemplos de XML para asegurarnos que salga como debe ser (no entiendo para qué, si todas las herramientas de generación de web services se encargan de que el XML siempre salga como debe ser, ¿verdad?).

Cuando tengo que invocar un web service, generalmente uso Axis2. Me ha resultado de lo más sencillo porque consiste simplemente en ejecutar el script wsdl2java dándole el URI del WSDL y con eso tengo una clase que puedo usar para invocar los servicios (junto con mil clases internas que envuelven los datos dentro de envoltorios intermedios porque parece que los de Axis entendieron OOP como Onion-Oriented Programming). Así que en esta ocasión decidí probar el otro lado de la implementación: publicar un servicio hecho con Axis2.

Comparativo de desempeño para formato de fechas

Comparto esto para los que tengan la misma duda que yo tenía: Saber si es más rápido usar String.format o un SimpleDateFormat para formatear una fecha.

Es claro que String.format puede ser más simple de codificar, sobre todo en ambientes concurrentes, ya que SimpleDateFormat no es thread-safe y por tanto hay que usarlo solamente de manera local o bien envolverlo en un ThreadLocal.

Pero pues hice un programa muy simple en Groovy para comparar el performance de ambos:

import java.text.SimpleDateFormat

SimpleDateFormat df = new SimpleDateFormat('yyyyMMddHHmmss')
Date now = new Date()
//calentamiento
10000.times {println df.format(now)}
10000.times {println String.format('%tY%<tm%<td%<tH%<tM%<tS', now)}
System.currentTimeMillis()

long t0=System.currentTimeMillis()
10000.times {
    df.format(now)
}
long t1 =System.currentTimeMillis()
10000.times {
    String.format('%tY%<tm%<td%<tH%<tM%<tS', now)
}
long t2 = System.currentTimeMillis()
println "SimpleDateFormat: ${t1-t0} vs String.format: ${t2-t1}"

Game Of Life en Ceylon

En el Code Retreat que hubo en Agosto de 2012, el reto fue implementar el famoso Game of Life, en parejas. En mi equipo, @juwe y yo lo desarrollamos en Ceylon (no me impuse; él se animó, jejej).

Apenas hoy lo pude subir a un repositorio que tenemos en GitHub especialmente para ejemplos de Ceylon, después de darle una buena actualizada al código porque han habido varios cambios en la sintaxis y en el módulo de lenguaje desde que escribimos esto originalmente: ya teníamos comprensiones, funciones de orden superior, funciones anónimas y varias otras cosas, pero no teníamos por ejemplo el assert, tuplas, ni la sintaxis actual para secuencias y colecciones iterables; la sintaxis para funciones anónimas cambió ligeramente, al igual que la de parámetros variádicos (los famosos varargs).

Migrar de Subversion a Git, sin mirar atrás

Este post no es realmente acerca de Java, pero quiero dejarlo en este sitio de todas maneras, ya que realmente no tengo otro blog y además no deja de ser algo muy técnico.

En mi trabajo desde hace varios años utilizamos Subversion, pero decidimos pasarnos a Git. El mismo Git incluye herramientas para integración con svn, pero son algo limitadas. Además creo que es un buen pretexto para aprovechar y reorganizar el repositorio, partiéndolo en varios repositorios distintos, abandonando algunas cosas obsoletas, ramas que llevan años abandonadas, etc.

En mi búsqueda por lograr esto, me encontré con esta herramienta llamada svn2git:

http://www.gitorious.org/svn2git

Parece que la desarrolló el equipo de KDE, para realizar lo mismo que yo estaba buscando: migrarse de una buena vez de svn a git, sin mirar atrás, reorganizando su código en varios repositorios, etc.

Esta herramienta está hecha en C++ y requiere Qt para poderse compilar, aunque no tiene interfaz gráfica. Debe ejecutarse en el servidor que contiene el repositorio de Subversion que se quiere migrar (no una copia de trabajo).

Comprehensiones en Ceylon

Las comprehensiones (o algo que se les parezca) son una característica ya prácticamente obligatoria en los nuevos lenguajes, al menos si quieren ser considerados cool. Y Ceylon no se queda atrás.

Las comprehensiones en Ceylon funcionan usando una variante especial de for, la cual acepta una sola expresión, en vez de un bloque de código. La expresión puede ser a su vez otro for, o bien un if, que actúa como un filtro, o cualquier otra expresión que devuelva algún valor. Todo eso termina siendo azúcar sintáctica para crear y devolver un objeto Iterable que se puede pasar en invocaciones a métodos o funciones que esperan argumentos secuenciados (de los que terminan con elípsis), o usarse directamente en cualquier lugar donde se pueda usar un Iterable.

Esto a fin de cuentas puede ser más poderoso que tener métodos como map y filter en las colecciones, y además permite hacer implementaciones más eficientes, ya que los iteradores intermedios involucrados se van utilizando conforme se necesitan, en vez de tener que procesar completamente una colección antes de pasar a la siguiente fase.

Si usan Groovy o Scala, puede que ya estén familiarizados con algunas de estas operaciones. Por ejemplo, tomar una lista de palabras y devolverlas en reversa:

["hola", "mundo", "javaMexico", "Ceylon"].collect { it.reversed() } //Groovy

List("hola", "mundo", "javaMexico", "Ceylon").map { _.reverse } //Scala

for (w in { "hola", "mundo", "javaMexico", "Ceylon" }) w.reversed; //Ceylon

Funciones en Ceylon, segunda parte

En mi post anterior, hablé acerca de las funciones de orden superior, la manera en que se pasan referencias a métodos, cómo se invocan, etc. Pues bien, ha habido bastante progreso en Ceylon, en varias áreas, y una de las que considero importantes es precisamente el manejo de funciones; algunas de las cosas que mencioné en ese post han cambiado, mientras que ha surgido funcionalidad nueva que no estaba disponible previamente. Así que veamos los cambios:

Callables

Primero que nada, ya no tenemos la restricción de que un Callable no podía ser invocado; ahora ya se puede, por lo que esto ya es válido:

value obj = MiClase();
Callable<String,Integer> f = obj.metodo;
String s = f(1);

La otra forma sigue siendo igual de válida:

value obj = MiClase();
//Aqui usamos inferencia de tipos
function f1(Integer x) = obj.metodo;
//Aqui ya lo definimos de manera estática
String f2(Integer x) = obj.metodo;
String s1 = f1(1);
String s2 = f2(2);

Argumentos por nombre

En Ceylon hay dos formas de hacer una invocación: usando argumentos posicionales (que es la manera en que todo mundo está acostumbrado a hacerlo) o usando argumentos nombrados (que no todos los lenguajes tienen y los que lo tienen, usan distintas sintaxis).

Ceylon M2

El segundo release de Ceylon, M2 aka "Minitel", ya está disponible.

Algunos de los cambios más importantes desde M1 que salió en diciembre, están:

  • Interoperabilidad con Java - ya se puede invocar código Java desde Ceylon, con algunas restricciones pero en general ya está funcionando.
  • Referencias a funciones y métodos - con esto hay bastante avance en lo que respecta a funciones de orden superior; ya se pueden pasar referencias a métodos y/o funciones como parámetros a otros métodos/funciones y también puede haber métodos/funciones que devuelvan Callables. Asimismo, se pueden definir métodos o funciones simplemente asignándoles una referencia a otro método o función que tenga la misma firma.
  • Performance - se optimizaron las operaciones aritméticas con Integer y Float, así como algunas operaciones que requieren boxing/unboxing (principalmente para interoperar con Java)
  • SDK más completo - El SDK ya incluye varias interfaces y clases para colecciones: Collection, Array, List, Map, Set, FixedSized, etc.

Funciones de orden superior en Ceylon

Ceylon tiene una característica que en lo personal me parece muy atractiva, algo que en otros lenguajes anuncian con gran fanfarria pero en Ceylon no se ha hecho tanto barullo. Es algo que creo que ayudará mucho para el diseño de APIs en el futuro cercano. Se trata de las funciones de orden superior.

Visto de manera simple, las funciones de orden superior son funciones que reciben otras funciones como parámetros, o bien que devuelven funciones como valor de retorno. El concepto realmente no es complejo; el truco en lenguajes de tipado estático está en que la sintaxis no sea compleja (en lenguajes dinámicos es muy sencillo pasar una referencia si no se tiene que indicar el tipo de retorno de la función, ni su número ni tipo de argumentos).

Una cosa muy necesaria para poder manejar funciones de orden superior en un lenguaje de tipado estático, es tener un tipo que las represente. En el caso de Ceylon, tenemos la clase Callable. Podemos usar este tipo para guardar la referencia a un método de un objeto por ejemplo. Suponiendo que tuviéramos una clase MiClase con un método metodo que reciba un entero y devuelva un string, entonces podemos hacer esto:

MiClase obj = MiClase();
Callable<String,Integer> f = obj.metodo;

Ojo, no es lo mismo obj.metodo() (lo cual es una invocación al método) que obj.metodo, que es simplemente obtener la referencia a ese método; a partir de entonces se puede manejar como una función.

Operadores en Ceylon

El capítulo 6 de la especificación de Ceylon trata de los operadores. Recientemente he estado implementando algunos de estos para el compilador de Ceylon a Javascript y me doy cuenta de que realmente son bastante convenientes, y pues quiero compartir algunas de sus peculiaridades, ya que algunos caben dentro de lo que muchos llaman "azúcar sintáctica".

Los más básicos no son nada extraños; por ejemplo para obtener un miembro de un objeto, simplemente es objeto.miembro; una invocación (a función o método) es con paréntesis, si van a usar argumentos posicionales: f() o f(a,b,c); pero si van a usar argumentos con nombre (cosa que se puede hacer cuando la definición de la función o método tiene argumentos con valores por default y simplemente se los quieren saltar), entonces usan llaves: f{a=1;b="2";}.

La asignación a variables (ojo: variables, no valores inmutables) es como en Pascal, con := pero hay un par de variantes interesantes: en vez de hacer var:=var.f, pueden abreviarlo como var.=f. Y en vez de hacer var:=var.f(x), pueden escribir var.=f(x).

Hola Ceylon, adiós NullPointerException

Todo programador que haya hecho aunque sea la más pequeña aplicación en Java, se ha topado en algún momento con la odiosa NullPointerException. Una excepción que sólo ocurre en tiempo de ejecución, cuando resulta que nuestro código invoca un método o quiere obtener un miembro de un objeto que realmente apunta a null. Y puede ocurrir por cosas tan simples como esto:

String x = "hola";
//algunas líneas más abajo...
if (cualquierCosa) { hola = null; }
//y otras líneas más abajo
int largo = x.length();

El código compila perfectamente. Es más, esto es código que compila sin darnos ningún error, ni advertencia, ni nada:

String x = null;
x.length();

Y uno se pone a pensar... es tan difícil que el compilador se diera cuenta que tengo una variable que apunta a null, y en la siguiente línea estoy invocando un método sobre ese null??????; pero pues así funciona Java. Y si lo anterior es posible, por supuesto puede ocurrir dentro de cualquiera de nuestros métodos que esperan recibir un objeto.

Distribuir contenido