ServiceConstructionException: Could not find definition for service

Ok… just for the record, Al implementar un client ws con cxf tener cuidado de no estar usando un frontend proxy factory en lugar de un jaxws proxy factory como, en general, queremos.

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.setServiceClass(MyService.class);
factory.setAddress("http://localhost/ws");
MyService client = (MyService) factory.create();

EasyMock: Mocks… eh… fácil.

El TDD es muy lindo hasta que nos toca hacer un test unitario a un componente que tiene muchas dependencias, que en estos tiempos de arquitecturas multitier suelen ser la mayoria.

Estas dependencias suelen remplazarse por objetos que simulan ser los reales compartiendo la misma interfaz. Claro que es solo una fachada, su implementación dista mucho de ser la real, pero nos proporcionan un comportamiento determinista y controlado contra el que probar nuestros componentes. EasyMocks es un framework que permite crear estos objetos de forma muy sencilla indicando cual es la interfaz que deben cumplir y cual es el comportamiento que esperamos.

Creando el Mock

Lo primero que necesitamos es decirle al framework cual va a ser la interfaz que queremos implementar en nuestro “mock”. Supongamos que necesitamos testear una clase Cliente que necesita los favores de una clase que implemente Servicio. Lo que vamos a hacer es un “mock” que simule ser una implementacion real de Servicio pero solo la vamos a usar para llevar a cabo el test.

El metodo estatico createMock de la clase EasyMock toma una Interface como parametro (tambien puede ser una clase) y nos devuelve un objeto que la implementa.

Servicio servicioMock = EasyMock.createMock(Servicio.class)

Its Alive!!

Genial, ¿Ya podemos pasarle la referencia servicioMock al Cliente y testear a gusto?… bueno… no tan easy.

A continuacion vamos a hacer que ese servicioMock implemente la operacion sumarDiez que, a partir de un parametro int numero devuelve ese numero incrementado en 10. No va a ser la implementacion real, solo a ’simular’ que esta haciendo algo realmente mediante el metodo EasyMock.expect.

EasyMock.expect(servicioMock.sumarDiez(5)).andReturn(15);

Acabamos de decirle a nuestro servicioMock que cuando alguien invoque al metodo sumarDiez con el numero 5 como parametro el debe devolver 15. No hay implementacion real, solo se pretende estar realizando la operacion. Ademas nuestro mock no sabe que hacer si alguien le pasa el numero 6 como parametro, y nos lo hara saber con una hermosa excepción.

Easymock.replay(servicioMock);

Esto pone al mock en ‘test mode’ indicando que ya podemos usarlo para nuestro test.

Still alive… and well?

Ahora sí podemos meter el servicioMock en nuestro test y admirar a EasyMock en toda su gloria

Ojo que lo que estamos testeando es el comportamiento de Cliente y no de Servicio! es decir que invocarAlMetodoSumarDiezDeServicio() este delegando correctamente e invocando a Servicio.

Cliente cliente = new Cliente();
cliente.setServicio(servicioMock);
int esultado = cliente.invocarAlMetodoSumarDiezDeServicio(10);
assertEquals(15,resultado);

Las posibilidades que tiene Easymock son ilimitadas y podemos simular comportamientos extremadamente complejos. Pueden encontrar mas informacion sobre todo el potencial de EasyMock en su página oficial.

Scripting en Java

En Java es posible interpretar virtualmente cualquier lenguaje de scripting utilizando una API bastante simple introducida  a partir de la versión 1.6  por obra de la JSR223. Estos lenguajes se incorporan en nuestros proyectos como simples Jars que luego son descubiertos por un ScriptEngineManager que los regentea.

JSE6 incorpora out-of-the-box el engine Rhino asi que tenemos la posibilidad de ejecutar código JavaScript en nuestras aplicaciónes haciendo poco y nada.

 ScriptEngineManager scm = new ScriptEngineManager();
ScriptEngine jsEngine = scm.getEngineByName("JavaScript");

Uhm… listo! estamos listos para interpretar javascript. Por un proceso de discovering (siguiendo la linea de los *Manager de Java) el ScriptEngineManager sabe que hacer cuando le pedimos un Engine de “JavaScript” y nos devuelve una instancia de ScriptEngine.

String script = "var sum = 0; var obj = new Array(1,1,2,3,5,13);"
+ "for each (var item in obj) { sum += item; }"
+ "print(sum);";
jsEngine.eval(script); // 25

el metodo eval del ScriptEngine interpreta el String que le pasamos como parametro y en la consola terminariamos con un “25″. However, el scripting en Java es mucho más inteligente, el metodo eval devuelve un Object que contiene el valor del ultimo statement del script. El mapeo del valor que ‘retorna’ el script contra los tipos de datos de Java es especifico del Engine por lo que nos vamos a encontrar con comportamientos diferentes segun el lenguaje (y el engine) que interpretemos.

 String script = "var sum = 0; var obj = new Array(1,1,2,3,5,13);"
+ "for each (var item in obj) { sum += item; }"
+ "sum;";
Double d = (Double) jsEngine.eval(script);
 System.out.println( d +1 ); //26!!!

Con esta feature de JSE6 es inevitable pensar en dar un paso más en la parametrización de nuestros sistemas  ya no solo parametrizando valores y constantes sino también la logica de determinados procesos a traves de scripts simples en JS, Phyton, Ruby, Groovy, Jaskell o lo que sea. Otra ventaja en el uso de de esta API esta en incorporar lenguajes que nos eliminan el ciclo de code-compile-deploy-test pero sin alejarnos de la plataforma Java.

Serialización con XML

En ciertas situaciones una forma más prolija de serializar un objeto consiste en convertir su estado en una definicion XML y guardarlo o enviarlo donde haga falta. Esto nos permite poder ver el estado del objeto sobre el stream persistido incluso modificarlo con un editor de texto, cosa impensable sobre la salida de una serializacion estandar. Para tal fin podriamos complicarnos usando XStream o alguno de los tantos OXM (Object XML Mapper) que hay dando vueltas por la red. Calma! Antes de bajar los 20MB de librerias que nos pide el Apache Digester podemos echarle un vistazo a dos clases incluidas en J2SE: XMLEncoder y XMLDecoder.

Estas clases sirven exactamente para nuestros propositos: Transformar objetos en definiciones XML, y definiciones XML en objetos, sin perder nada en el medio. Sin configuraciones ni descriptores extraños estas dos clase son tan faciles de usar como un ObjectInputStream y objectOutputStream.

Objeto -> XML

 Perro p = new Perro();
      FileOutputStream f = new FileOutputStream("perro.xml");
  XMLEncoder xe = new XMLEncoder(f);
      xe.writeObject(p);
      xe.close();

XML -> Objeto

  FileInputStream f = new FileInputStream("perro.xml");
  XMLDecoder xd = new XMLDecoder(f);
      Perro p = (Perro)xd.readObject();

Esta demas decir que el XML contiene todo el grafo del objeto (el perro con sus pulgas, collar, dueño y cualquier otra dependencia) haciendose cargo de forma impecable de las referencias circulares.

Los drawbacks de este metodo si lo comparamos con la serializacion tradicional es el mismo que se le atribuye a RMI vs Webservices: El XML es mas lento y pesado que su par binario. A favor de este método podemos decir que el objeto serializado es un xml que puede editarse en cualquier lado y que se elimina el problema del cambio de version de las clases. Ya no hay que preocuparse por conflictos de versionado con el serialVersionUID porque la unica informacion que se guarda en el xml sobre la clase de las instancias es el nombre.

La inmutabilidad de los Objetos

En el mundo de la OOP existe un tipo de Objeto denominado “Inmutable” que consiste en un objeto en el que su estado, una vez definido, no cambia durante todo su tiempo de vida.

Java incorpora unos cuantas clases cuyas instancias tienen la propiedad de ser inmutables. Las clases que envuelven los tipos primitivos (Byte, Short, Character, Integer, Long, Float, Double) son inmutables. La clase String es inmutable. ¿Por qué son inmutables?¿Para complicarnos la existencia? No realmente…

Asi como en el experimento del Gato de Schrödinger creamos una clase Gato con un atributo estado de tipo String. El estado del gato nos dice si el gato esta “VIVO” ó “MUERTO”

public class Gato {
    private String estado;
    public void setEstado(String e) {
    this.estado = e;
    }
    public String getEstado() {
    return estado;
    }
}

vamos a suponer que la clase String tuviera un metodo setValue() que me permita cambiar la cadena de texto almacenada en una instancia particular de String. Es decir, supongamos que los objetos String no son inmutables y podemos cambiar el texto que contiene.


public class TestSchrödinger {
public static void main(String[] args) {
Gato gato = new Gato();
String e = "vivo";
gato.setEstado(e);
//El gato esta vivo :)
e.setValue("muerto");
//A nuestro String mutable le cambiamos el texto que encapsula.
System.out.println(e);
//Si esto es cierto entonces deberia salir impreso en la pantalla "muerto"
System.out.println(gato.getEstado());
//¿El gato esta vivo o esta muerto?

El problema de la mutabilidad consiste en que los parametros en Java siempre son pasados por valor, inclusos las referencias a objeto pero no el objeto al que apunta. Si un String, por ejemplo, podria cambiar el valor que contiene entonces aparecerian inconsistencia en el estado de los objetos que en algun momento incorporaron ese String a su estado.

Si no les quedo muy claro tal vez este video ayude un poco ;)

Entradas y comentarios feeds. 14 queries. 0.254 seconds.

60921 pages viewed, 16 today
29270 visits, 11 today
FireStats icon Powered by FireStats