Aprende

Aprende sobre la última tecnología.

Construye

Da rienda suelta a tus conocimientos y construye!

Comparte

Que más gente lo aproveche para mejorar!
 

Como crear USB de CENTOS booteable desde Mac

miércoles, 18 de noviembre de 2015

En los últimos tiempos, al menos en el mundo mac no se lleva lector cd/dvd y realmente resulta mucho más cómodo tener nuestra información en la nube o en discos portátiles. Nuestro comentario de hoy y luego de varios meses sin escribir, será relacionado con el modo de crear un USB booteable desde Mac. Aunque detallo que es para CENTOS, podemos destacar que dicha operatoria es válida para cualquier imagen booteable y que queremos sea arrancada para instalar cualquier sistema operativo del que tengamos una imagen.

Pasos a seguir :
  • Copiamos la imagen iso a un path determinado y nos movemos allí. Como consejo poner un nombre lo mas simple posible a la imagen y de ser posible sin espacio, no es nada necesario, solo por facilidad con su tratamiento en la consola.
  • Una vez que copiemos la imagen iso, ejecutamos el siguiente comando :
diskutil list

Y obtendremos como resultado la siguiente pantalla/o una equivalente en consola que nos indica todos los discos y las particiones de los mismos.




  • Lo siguiente que sigue es desmontar todos los volúmenes del disco que queremos que sea booteable. Miramos el resultado de la anterior pantalla ,en nuestro caso /dev/disk1 y será el que tendremos que desmontar. El comando a lanzar es el siguiente:

sudo diskutil unmountDisk /dev/disk1  

Un detalle importante a tener en cuenta es el disco correcto a desmontar y por otra parte el  resultado de la operación, que nos indicara si ha finalizado con éxito o no.
  • Una vez que tenemos desmontada la unidad vamos a trabajar sobre ella, mi recomendación es movernos hacia la carpeta donde tenemos la imagen iso copiada,una vez que estemos allí ejecutamos el siguiente comando:

sudo dd if=file_name.iso of= /dev/disk1 bs=1m  

Aunque no vamos a profundizar en un comando como dd si quisiera detallar algunos aspectos.El parámetro input file(if) vamos a indicar nuestra imagen, si no estamos en el directorio actual podemos indicar el path del fichero path_del_fichero/file_name.iso, el output file(of) es que nuestra copia la vamos a redirigir a un fichero que estará en el siguiente disco y volumen,el parámetro bs, aunque es opcional es muy importante no olvidarlo ya que el valor por defecto es 512 bytes y ello indica el tamaño de los bloques transferidos a la vez con lo que el valor por defecto para imágenes grande implicara que el proceso tarde mucho mas de lo habitual.

Otro aspecto a destacar es que una vez lanzado el comando se nos queda la pantalla negra esperando por un gran espacio de tiempo sin indicarnos ningún progreso solo el resultado de la operación cuando esta termina y que es una pantalla similar a la siguiente:


Como podemos ver hablamos de solo tres comandos, sin tener que realizar engorrosas instalaciones de softwares que en teoría te hacen el mismo proceso.
Cabe destacar que si necesitaramos  instaladores para otros mac y SOLO en le caso de booteables para windows,que no sería este nuestro caso ahora, a partir de la versión 10.8 del LION tenemos el asistente Boot Camp para ello. Aunque obviamente es mas útil la versión aquí explicada ya que es válida para cualquier combinación.







Servicios RESTful con Scala via Spring

martes, 11 de agosto de 2015

El objetivo final de esta entrada será que el lector pueda implementar servicios REST usando Scala en la operatoria y problemática de los servicios y Spring como transporte de los mismos. Recomendamos sino tiene conocimientos de Restful con Spring la lectura de la anterior entrada de Spring en este mismo blog Restful con spring.

En alguna entrada anterior he mencionado el uso de sbt  y de mi preferencia de no usarle en determinadas situaciones, esta es una de ellas, Spring con Scala, aunque tengo que reconocer que los de http://pivotallabs.com han hecho un trabajo interesante con ello. Recomiendo ver la siguiente prueba http://pivotallabs.com/spring-4-mvc-scala/; lo cual es prácticamente lo mismo que intentaremos hacer en nuestra entrada de hoy pero diferenciando el modo de construcción. En el ejemplo http://pivotallabs.com/spring-4-mvc-scala/ implementan navegación con Springmvc y la construcción con sbt, en nuestro caso implementaremos Servicios restfull con Spring y la construcción del mismo lo haremos con maven. En próximas entradas y con proyectos más complejos comenzaremos a usar  esta configuración que nos muestra pivotal, que ya tiene mas de un año desde las fases de prueba y parece ser la más indicada de una manera natural.

Otra vía, creo que la más natural para tratar Restful con Scala y específicamente para peticiones HTTP tanto request/response JSON debería ser Scala con Play, esta sería la solución ideal en el momento que conozcamos a fondo un PaaS, en mi caso no sé cómo se adaptaría esta solución a Openshift,único PaaS que de momento conozco.

La siguiente clase es una clase controladora, que simplemente llama a un servicio. Solo dos cosas a destacar la linea 22 es una definición del método y además retorna una lista que será un JSON de 3 elementos. Algo muy importante en esta linea 22 es la siguiente porción de código  java.util.List[Greeting] =  ....  en ella vemos que el tipo que devuelve nuestro servicio es una lista java sin embargo la lista gestionada dentro del servicio es una lista de Scala. Esta conversión(no es un CAST )  es de manera automática y es posible debido a la importación que hacemos en la linea 14 de collection.JavaConversions.

GreetingController.scala
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.ldg.spring.rest.controller

import com.ldg.spring.rest.service.Greeting

import org.springframework.web.bind.annotation.RequestParam
import java.util.concurrent.atomic.AtomicInteger
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.MediaType
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.ResponseBody
import scala.collection.immutable.List
import collection.JavaConversions._

@Controller
@Autowired
class GreetingController {

    @ResponseBody
    @RequestMapping(value=Array("/greeting"),method = Array(RequestMethod.GET))
    def greeting(@RequestParam(value="name", required=false, defaultValue="World") name: String) : java.util.List[Greeting] = {
         List(Greeting(1, name+"1"),Greeting(1, name+"2"),Greeting(3, name+"3"));
    }
 }

Después de ver nuestra anterior porción de código solo cabe una pregunta: ¿Por que convertir la lista de Scala a una lista de Java?La principal causa es la linea 8 del siguiente fichero de configuración(springContext.xml), aquí usamos el propio parser de mensajes a JSON que tiene Spring. Si la lista a retornar fuera una lista de Scala necesitaríamos hacer un conversor de JSON personalizado para nuestro tipo(jsonHttpMessageConverter,programado para Scala), tarea bastante ardua y que podría dar para otra entrada. Es probable que para un JSON más personalizado debamos hacer nuestro propio conversor.Con lo cual todas las response serán convertidas a JSON usando nuestro jsonHttpMessageConverter

springContext.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
    <mvc:annotation-driven/>

    <context:component-scan base-package="com.ldg.spring.rest" use-default-filters="false">
        <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>

    <!-- json handler -->
    <bean id="jsonHttpMessageConverter"
          class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
        <property name="supportedMediaTypes" value="application/json"/>
    </bean>
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="jsonHttpMessageConverter"/>
            </list>
        </property>
    </bean>

La siguiente clase es una implementación del servicio, también en Scala y estará implementado a través de una case class, como un tema interesante tenemos la anotación @BeanProperty cuya finalidad es adicionar internamente métodos setter y getter siguiendo la convención de los JavaBeans,ello permitirá que nuestro servicio pueda ser inspeccionado por Spring ,todo ello transparente al desarrollador.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package com.ldg.spring.rest.service

import scala.beans.BeanProperty
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.annotation.JsonInclude;

//@BeanProperty is required in order to have Java Bean Style getter/setter that can be inspected by Spring
/**
 * La siguiente anotacion no es necesario especificar que produce un JSON,ya lo solucionamos de manera declarativa 
 * en springContext-webapp.xml destacando que todo lo que se produzca sea convertido a JSON con lo que solo 
 * @JsonInclude(JsonInclude.Include.NON_NULL)
 *
 **/

@Service
case class Greeting(@BeanProperty id: Int, @BeanProperty content: String)

No mencionamos en nuestras entradas detalles sobre la construcción del proyecto. Lo dejamos para el lector quiera descargarse el proyecto y ya en ese caso verá los detalles.Este es un caso particular ,no estableceremos referencia aquí a ningún código solo un link al pom del proyecto, mirar las dependencias y plugins relacionados con Scala y su modo de construcción.No lo detallamos aquí sobre todo para no extender esta entrada,cualquier duda pueden postearla en github.

Este pequeño holamundo de Scala-Restful-Spring lo puedes descargar y ejecutar siguiendo sus instrucciones en mi github. Hemos visto lo sencillo de implementar un servicio en Scala, en cuanto a la arquitectura REST se refiere, otra cosa será la implementación del servicio en si, que con scala aunque todo es mas sintetizado en ocasiones suele ser complejo.

Hacemos un resumen de las principales anotaciones y variables reservadas
que usamos aquí:
@BeanProperty: Cuando adjuntamos esta anotación a un campo, la misma añade metodos setter y getter a dicho campo siguiendo la convención de los javabeans.
case class : Una case class es como una clase normal con 2 grandes diferencias , que exporta los parámetros de su constructor con lo que son tratados como públicos y se puede acceder a ellos de manera directa. Así pues para construir una instancia de una case class no necesitamos new, solo será suficiente el nombre de la clase y la llamada al método en cuestión.Existe otro uso bastante importante de las case class , diría que el más importante , el relacionado con pattern match pero que dejaremos para una entrada dedicada a Scala únicamente.







RestFul con Spring

lunes, 13 de julio de 2015



El objetivo final de esta entrada será que el lector implementar servicios REST usando Spring como transporte de dicho servicio. Estamos dando por supuesto que el lector sabe lo que es un servicio web así como que también sabe lo que es un servicio REST, en caso contrario tendrá que documentarse al menos de la teoría para poder entender lo que sigue a continuación. Existen diferentes vías para implementar servicios REST, en mi caso tengo experiencia en 2 de ellas:
  1. Jersey: Ligera y sencilla implementación de Oracle,es una implementación de su propio standard (https://jax-rs-spec.java.net).Como referencia tenemos los siguientes  proyectos en github(RESTfulJersey,RESTfulJsonhttps://github.com/ldipotetjob/Spring-Examples
  2. Spring MVC: Nuestra explicación estará basada en Spring 3.2.x aunque es justo decir que la version de Spring 4 ha salido con algunos cambios en el tratamiento de servicios REST, aunque la base y gran parte de la api sigue siendo la  misma.
Lo que ocupará nuestro artículo será  el .2, la implementación de servicios REST a través Spring; a pesar de que en el .1 he dejado referencia a dos proyectos muy simples ubicados en mi github,tan solo para que entiendan como va la implementación de Jersey. De cualquier manera mi recomendación es que entren en  https://spring.io/projects y echen una mirada a los proyectos que allí hay. Para mi merece especial atención el proyecto http://projects.spring.io/spring-hateoas/ basado en el principio de HATEOAS, en el cual entraremos a fondo en futuras entradas en este Blog.
Como cultura no es necesario leer ninguna especificación de ningún lenguaje pero si vamos a hacer un proyecto serio creo que puede ser muy buena idea. Aquí os dejo la especificación de RESTFUL.
Cualquier  tema referente a inyección de código y autowire sino lo tiene claro puede ir a la anterior entrada de Spring que tenemos en este blog http://mojitoverde.blogspot.com.es/2015/07/spring-de-base.html.

Aunque no profundizaremos respecto al scope de los beans, en esta entrada podemos resumirlo en la figura que sigue, importante destacar que Spring crea una instancia por cada bean que crea y a la vez esta también puede ser compartida la misma.Es un detalle importante, pero en el que no nos detendremos.Queda al lector investigar o esperar posibles entregas.

Scope de un bean





Spring MVC encapsula datos de la aplicación para mostrarlos a una vista, no nos detendremos en
explicar SpringMVC en su conjunto ya que hoy nuestro objetivo es simplemente como trata la implementación de servicios web de tipo Restful, de momento la estructura a elegir como respuesta a la request del servicio serán mensajes en formato JSON.

Para ir introduciendo el tema veamos el ejemplo mas simple de código que podemos tener :

1
2
3
4
5
6
7
8
9
@Controller 
@RequestMapping("/hello") 
public class HelloWorldController {
    @RequestMapping(method = RequestMethod.GET)
    public String helloworld() {
      //.....
        return "hello world!";
 } 
}

Nuestro análisis basándonos en el código anterior es el siguiente: la anotación @Controller indica que una clase es un controlador, recordemos que un controlador en Spring representa un componente que recibe instancias HttpServletRequest y HttpServletResponse, como HttpServlet y que además esta en el workflow de MVC. Como vemos, una clase que este anotada con @Controller no tiene necesariamente que implementar ninguna interface o extender determinada clase.Otro aspecto a destacar es que en una clase controladora podrán existir uno o más métodos handlers(métodos que realizarán la dinámica del servicio en cuestión).

La anotación @RequestMapping puede ser aplicada tanto a nivel de clase como a nivel de método. Tenemos varios patrones de diseño o trabajo, uno de ellos es el "helloworld" anterior en el que se mapea un particular patrón de URL a la clase controladora y luego un particular método HTTP en cada método handler. Nuestro @RequestMapping contiene propiedades interesantes de destacar tanto a nivel de clase como a nivel de método.El uso de @RequestMapping("/hello")  anotando la clase es usado para especificar la URL sobre la cual es activado el controlador ó clase controladora, que contiene los métodos handlers.Significando lo anterior que cualquier request que se reciba sobre la URL /hello será atendida por la clase controladora HelloWorldController.

Cuando llega la petición(request); se delega la llamada en el método HTTP GET que tenemos por defecto declarado en la clase controladora. La request inicial hecha sobre una url es siempre de tipo HTTP GET, por lo que basándonos en el ejemplo anterior, cuando la clase controladora atienda una request que venga de una URL /hello se delegará en el método HTTP GET. En nuestro caso será "helloworld" que aparece a su vez decorado con la anotación @RequestMapping(method = RequestMethod.GET).

La anterior porción de código solo contempla un método GET bajo la URL /hello de la clase controladora, pero imaginemos que queremos hacer el mapping a nivel de clase como en la anterior sección de código y que además necesitamos varios métodos GET sobre la misma clase controladora:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@Controller
@RequestMapping("/hello/*")
public class HelloWorldController {
private HelloService helloService;
@Autowired
public HelloWorldController(HelloService helloService) {
this.helloService = helloService;
}
@RequestMapping("greeting")
public String greetingWorld() {
//....
return "Hello world";
}
@RequestMapping("display/{user}")
public String displayUser(@RequestParam("season") String season,@PathVariable("user") String user) {
//....
}

Basándonos en el código anterior nuestra clase controladora atenderá una petición que venga de la URL /hello y luego la petición siguiente URL /hello/greeting será atendida en la linea 5 de manera equivalente sucederá lo mismo en la linea 14 ,que además incorpora otras anotaciones de interés como RequestParam y PathVariable.Vemos como se usa la anotación especial {path_variable} en linea 14 , para especificar su valor en el correspondiente @RequestMapping.Vea que se declara @PathVariable("user") String user; de este modo si se recibe una request con el siguiente formato /display/luis el método tendrá acceso a la variable "user", que tomará el valor "luis". De la misma manera @RequestParam lee el parámetro de season pasado en la request y lo asigna a una variable.

Otra opción es usar la anotación @RequestMapping a nivel de método tal y como indicamos en la siguiente porción de código:

1
2
3
4
5
6
7
8
@Controller 
public class HelloWorldController {
    @RequestMapping(value ="/hello",method = RequestMethod.GET)
    public String helloworld() {
      //.....
        return "hello world!";
 } 
}

Proponemos a continuación otro ejemplo del uso de la anotación @RequestMapping:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
@Controller
public class MemberController {
    private MemberService memberService;
    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
    @RequestMapping("/member/add")
    public String addMember(Model model) {
        model.addAttribute("member", new Member());
        model.addAttribute("guests", memberService.list());
        return "memberList";
    }
    @RequestMapping(value={"/member/remove","/member/delete"},method=RequestMethod.GET)
    public String removeMember(
            @RequestParam("memberName") String memberName) {
           memberService.remove(memberName);
           return "redirect:";
    }
}

En el código anterior tanto la linea  8 como la linea 14 muestran distintos patrones de uso de la anotación @RequestMapping.En ambos casos son llamadas a métodos HTTP GET. En la linea 14 establece que cualquier request que se reciba sobre la URL /member/remove/member/delete será atendida por el método removeMember,linea 15.

Hemos visto la anotación @RequestMapping anotando tanto a clases como a métodos y en ambos casos el objetivo es siempre el mismo, tratar una determinada request de una URL específica.

Existen aspectos que pueden resultar interesantes pero que escapan al ámbito de esta
entrada como puede ser atender una petición(request) teniendo en cuenta el tipo de la misma(HTTP POST,PUT,DELETE), GET esta dada por defecto.

Para cualquier tema referente a la configuración de los applicationContext ir a Spring Base en este mismo blog ó a la especificación de Spring https://spring.io/projects. En conjunto con las anotaciones será necesario configurar el fichero .xml para el IoC Container y el descriptor de despliegue(web.xml).

De cualquier manera vamos a destripar una pequeña aplicación de SpringMVC que devuelve un JSON que contienen una lista de elementos. Esta aplicación podrás encontrarla en mi GitHub Springmvc.
Analizaremos 2 de los ficheros fundamentales :
El descriptor de despliegue(web.xml)
El fichero de configuración del IoC Container

web.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    <!--.............-->
    <!-- spring DispatcherServlet servlet -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/mvc/*</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/springContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
   <!--.............-->

En la linea 4 tenemos el servlet de Spring encargado de gestionar las peticiones,DispatcherServlet. Es org.springframework.web.servlet.DispatcherServlet el servlet que recibe una petición(request) e intenta enviarla a las diferentes clases que han sido declaradas con la anotacion @Controller. Este proceso de envío dependerá de las diferentes anotaciones @RequestMapping declaradas en la clase controladora. Es importante destacar que en la linea 24 registramos el ContextLoaderListener listener de Spring que será el encargado de cargar el ApplicationContext. En la linea 18 indicamos el fichero de configuración del Ioc Container  que queremos cargar. Las lineas que hacen referencia al código y que hemos destacado son las principales a tener en cuenta en nuestro descriptor de despliegue, pero no las únicas. A partir de aquí podemos agregar cada elemento que necesitemos y que se acoja al standard de especificación para el descriptor web.xml, algo que también escapa al ámbito de este documento.

Hasta ahora solo hemos visto ejemplos en los que los servicios implementados solo devuelven un boleano o incluso un nombre que puede ser el de una vista para realizar cualquier otra operación. Pero en el verdadero uso de un servicio REST solemos retornar, en el caso de un servicio de tipo HTTP GET, un JSON ó también un XML. En nuestro caso vamos a abordar la problemática de un servicio REST que genere un JSON como respuesta a una petición HTTP GET.
Para ello nuestro servicio contará por una parte con la anterior porción de código correspondiente al descriptor web.xml  y por otra parte tal como anteriormente mencionamos, con el fichero de configuración del IoC Container.

fichero de configuración del IoC Container.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- .........................-->   
 <mvc:annotation-driven/>

    <context:component-scan base-package="com.ldg.spring.rest.controller" use-default-filters="false">
        <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>

    <!-- json handler -->
    <bean id="jsonHttpMessageConverter"
          class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
        <property name="supportedMediaTypes" value="application/json"/>
    </bean>

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="jsonHttpMessageConverter"/>
            </list>
        </property>
    </bean>
<!-- .........................-->

Hemos de destacar algunos detalles no tenidos en cuenta en anteriores entradas de Spring, en lo referente al código anterior,la linea 1 nos muestra un tag ,mvc:annotation-driven, el cual suministra una funcionalidad adicional en los módulos de Spring. No confundir su utilidad con la de context:annotation-config ya que mvc:annotation-driven es mucho más que la declaración de soporte para las anotaciones de manera general, en nuestro caso lo usamos a aquí para una la conversión de mensajes HTTP con @RequestBody/@ResponseBody, específicamente para el soporte de las librerías de Jackson para Spring. Queremos que el mensaje de respuesta en cuestión sea de formato tipo JSON y para ellos estamos usando Jackson con lo que necesitaremos mvc:annotation-driven para que nos brinde el soporte al mismo. De cualquier manera tiene una mas utilidad esta anotación, dejamos aquí un enlace referente al documento de la especificación que explica la misma (mvc:annotation-driven). En combinación con la anotación anterior tenemos la declaración de la linea 15,en la que agregamos un HttpMessageConverter.

Por qué necesitamos el HttpMessageConverter,hablando de la manera mas llana posible tanto las peticiones como las respuestas HTTP están basadas en texto con lo que el browser y el servidor se comunican intercambiando texto pero los métodos del  controlador retornan Objetos.El modo o la vía que Spring usa para serializar/de-serializar estos objetos a texto es gestionado a través del HttpMessageConverter.

En la linea 14 creamos un bean que sea será implementación de HttpMessageConverter que pueda tanto escribir y leer JSON usando el Mapper de Jackson 1.x .Este es el bean que usaremos para setear los HttpMessageConverter en AnnotationMethodHandlerAdapter y que permitirá convertir a JSON tanto peticiones y respuestas HTTP.

Recomiendo al lector que eche un ojo a las librerías de Jackson,proyecto bastante interesante y mas util de lo que solemos creer.

El código que tenemos en está deprecado en lo referente a el HttpMessageConverter.
Básicamente porque todo el conjunto de pruebas han sido hechas con la version 1.X de las librerias de JACKSON,debido a unas pruebas de rendimiento que me daban mejor tiempo con la version 1.x de Jackson para JSONs de mas pesados.Tenemos pendiente cambiar tanto esta entrada como el código de GitHub para versiones 2.x de Jackson.

Si aún así estuviera interesado el lector en una versión actualizada ,la siguiente porción sería la que necesitaríamos cambiar dado que quisiéramos cambiar a una versión no deprecada:

fichero de configuración del IoC Container.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.1.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

    <mvc:annotation-driven/>

    <context:component-scan base-package="com.ldg.spring.rest.controller" use-default-filters="false">
        <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>

    <!-- json handler -->
    <bean id="jsonHttpMessageConverter"
          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <property name="supportedMediaTypes" value="application/json"/>
    </bean>

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="jsonHttpMessageConverter"/>
            </list>
        </property>
    </bean>

</beans>

Mirar los cambios en linea 20 y en linea 25. Además habrá que cambiar en el pom.xml del proyecto las dependencias a las nuevas librerias de jackson (2.x).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
       <!-- Jackson dependency -->
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.12</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-asl</artifactId>
            <version>1.9.12</version>
        </dependency>

Como referencia el pom.xml a cambiar esta ubicado en mi github.

A continuación tenemos una porción de la clase controladora que hace además uso de  los ficheros de configuración anteriormente expuestos(web.xml y fichero de configuración del IoC container):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//..............................
@Controller
public class StatusController {

    private StatusService statusService;
    private TrackJsonService trackService;
    
    @Autowired
    public StatusController(StatusService statusService,TrackJsonService trackService) {
        this.statusService = statusService;
  this.trackService = trackService;
    }

    @ResponseBody
    @RequestMapping(value = "/status", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public StatusJson findStatus() {
        return new StatusJson(statusService.getStatus());
    }

    @ResponseBody
    @RequestMapping(value = "/track", method = RequestMethod.GET/*, produces = MediaType.APPLICATION_JSON_VALUE*/)
    public List<Track> findTrack(@RequestParam(value = "usr", required = false) String varjson) {
 
        return trackService.getTrackInJSON(varjson);
    }

}

//............

Mirar tanto la linea 14 como la linea 21 y en ambas el atributo produce de @RequestMappping,en uno de los casos está comentados y nos devuelve un JSON. No necesitamos este atributo, ya tenemos un messageconverter registrado en el fichero de configuración del Ioc Container con lo que todas las respuestas serán convertidas a JSON, esta es una de las grandes ventajas de los conversores pero que solo tienes su lógica en los casos que siempre tengamos respuestas en determinados formatos.

Las siguientes lineas de código son un porción de la implementación del servicio:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//.....
@Service
public class TrackJsonServiceImpl implements TrackJsonService {

public List<Track> getTrackInJSON(String varjson) {
 // TODO Auto-generated method stub
 
 List<Track> listtrack = new ArrayList<Track>();
 Track track = new Track();
 track.setTitle("Enter Sandman _" +varjson);
 track.setSinger("Metallica");
 
 Track track1 = new Track();
 track1.setTitle("Fragile _" +varjson);
 track1.setSinger("Sting");

 
 Track track2 = new Track();
 track2.setTitle("Imagine");
 track2.setSinger("Beattles _" +varjson);

 listtrack.add(track);
 listtrack.add(track1);
 listtrack.add(track2);
 
 return listtrack;
 
} 
//.....

Interesante ver la anotación de la linea 2, @Service,una especialización de @Component y que ayudará entre otras cosas a que pueda ser encontrado e inyectado el componente cuando se realice un scan indicando en el fichero de configuración del Ioc Container.


Hacemos un resumen de las principales anotaciones usadas aquí:
@Controller: Anota la clase que será  el controlador en MVC y manejara las peticiones HTTP.
@RequestMapping: Anota funciones que deberán manejar metodos HTTP, URIs ó HTTP Headers
@PathVariable: Una variable en la URI que puede ser inyectada usándola anotación @PathVariable.
@RequestParam: Usamos esta anotación para inyectar un parámetro de una URL en un método.
@RequestHeader: Usamos esta anotación para inyectar un HTTP HEADER en un método.
@RequestBody: Usamos esta anotación para inyectar el body de una request HTTP en un método.
@ResponseBody: Retornar un contenido u objeto como un HTTP  response body.
@Service:Es una especialización de @Component.


Nuestra próxima entrega tendremos un ejemplo muy simple a ir introduciendo de Scala con Spring.



Spring de base

miércoles, 1 de julio de 2015

Andamos de vuelta con muchos artículos pendientes.Mucho hay sobre Spring en la red con lo que solamente haré una breve introducción para aquellos que no controlan framework. Solo con el objetivo de que tenga un recordatorio para posteriores entradas en las que aunque Spring no será el centro del problema, lo usaremos como ayuda básicamente para servicios REST,de ahí la razón de esta entrada en nuestro blog.

Pasada esta breve INTRO entramos en materia y no veo otra manera que comenzar por la esencia de Spring: 
  • La inyección de código y esa es la base a partir de la cual transcurre  todo el  ciclo de vida de toda aplicación Spring. 
  • El IoC Container es aquí donde encontramos toda la configuración de Spring para nuestra aplicación así como todos los elementos(beans) que se inyectarán en nuestro código.
La configuración del IoC Container puede ser hecha programáticamente(a través de código) o de una modo declarativo a través de un fichero (.xml) de configuración. En nuestro caso abordaremos todo el articulo basándonos en el modo declarativo de configuración.
Lo siguiente es una configuración para un "HelloWorld" muy simple pero que nos permitirá ver como Spring inyecta el código usando la configuración  establecida en el IoC Container. La configuración la establecemos en un fichero xml (beans.xml), que deberá estar en el classpath de nuestro proyecto, podemos  establecer el nombre que queramos no tiene que ser applicationContext.xml.

   beans.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="christmas" class="com.ldg.spring.hello.Holiday">
        <property name="month" value="12" />
        <property name="day" value="25" />
        <property name="greeting" value="Merry Christmas!" />
    </bean>

    <bean id="newYear" class="com.ldg.spring.hello.Holiday">
        <property name="month" value="1" />
        <property name="day" value="1" />
        <property name="greeting" value="Happy New Year!" />
    </bean>

    <bean id="helloWorld" class="com.ldg.spring.hello.HelloWorld">
        <property name="message" value="How are you?" />
        <property name="holidays">
            <list>
                <ref local="christmas" />
                <ref local="newYear" />
            </list>
        </property>
    </bean>
</beans>

De la linea 1 - 4 tenemos la configuración xml para usar los tags establecidos en el esquema en cuestión. El caso anterior es una de las configuraciones más simples posible. Una vez que la tenemos establecida en el IoC Container necesitamos instanciar el mismo. Lo haremos de la siguiente manera:

1
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

Es en ese momento(linea 1) cuando creamos una instancia del Application Context presente en nuestro IoC Container. Baste decir que a pesar de que dicha instancia la creamos a partir  de ClassPathXmlApplicationContext  existen varias vías para crear una instancia de nuestro Application Context, por ejemplo:
FileSystemXmlApplicationContext vía usada para cargar ficheros XML de configuración desde el fileSystem o incluso desde URLs para el caso de las aplicaciones web se podría usar  XmlWebApplicationContext.

Una vez que tenemos una instancia del IoC Container, en la linea 1 del código anterior ya podemos obtener cualquier bean de los declarados(lineas 6,12 ó 18) en el fichero de configuración(beans.xml).

1
2
3
4
5
     //"helloWorld" es el id del bean declarado en el IoC Container
     //El cast es obviamente la clase identificada con el bean,declarado en 
     //el IoC container

     HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");

Toda vez que ya tenemos los beans podemos usarlos para la funcionalidad que necesitemos. Un detalle a destacar es que podríamos cargar en nuestro contexto varios ficheros de configuración. Imaginemos que queremos dividir los ficheros de configuración agrupándolos por determinada funcionalidad.Pues ubicando los ficheros en el classpath del proyecto cargaremos dicha configuración en  IoC Container. La manera de cargar los ficheros de configuración sería la siguiente:

1
2
3
ApplicationContext context = 
     new ClassPathXmlApplicationContext(new String[] {"beans.xml",
              "beans2.xml","beans3.xml"});

Una manera más profesional podría ser crear un solo fichero de configuración que importe a su vez todos los ficheros de configuración que tengan los beans separados por cada funcionalidad. Un ejemplo claro podría ser el fichero de configuración siguiente :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
    <import resource="beans.xml" />
    <import resource="beans2.xml" />
    <import resource="beans3.xml" />
 
</beans>

Donde además solo será necesaria una instancia de IoC Container para luego obtener el bean que necesitemos y sus correspondientes funcionalidades.
El resto del ciclo de vida hasta la carga de cada bean en cuestión sería del mismo modo que hemos explicado anteriormente.



Esta es la esencia de Spring, a partir de este punto tenemos una serie de aspectos a tener en cuenta que dependerá de cuanto seamos capaces de profundizar respecto a nuestras necesidades :
  • podemos establecer propiedades,en los beans declarados en los ficheros de configuración,para luego inyectarlas:
1
2
3
4
5
6
7
8
    <bean id="dataSource" class="com.ldg.spring.BasicDataSource">
        <property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"/>
        <property name="url" value="jdbc:derby://localhost:1527/vehicle;create=true"/>
        <property name="username" value="app"/>
        <property name="password" value="app"/>
        <property name="initialSize" value="2"/>
        <property name="maxActive" value="5"/>
    </bean>
  • podemos  inicializar objetos a través de un constructor desde el IoC container:
1
2
3
4
5
   <bean id="constructorCourseConstructor" class="com.ldg.spring.ConstructorCourseWithConstructor">
  <constructor-arg value="30" />
  <constructor-arg value="A" />
  <constructor-arg value="100000" />
    </bean>
  • podemos incluso tener un bean parent con una funcionalidad y luego un bean hijo que herede esa funcionalidad del parent y que además tenga otras funcionalidades:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<!--ver la ref suffixes--&gt;
   <bean id="baseConstructor" abstract="true">
        <property name="initial" value="100000" />
    </bean>

    <bean id="baseSpringConstructor" abstract="true" parent="baseConstructor"
        class="com.ldg.spring.sequence.SequenceGenerator">
       <property name="suffixes">
            <ref local="setsuffixes" />
        </property>
      
    </bean>

    <util:set id="setsuffixes">
        <value>5</value>
        <value>10</value>
        <value>20</value>
    </util:set>

En el ejemplo anterior bean parentbaseConstructor bean hijobaseSpringConstructor ,la linea 14 nos indica una colección que podrá ser inyectada en el bean,en este caso ha sido un Set pero podría ser un List o Maps u otra colección. Pueden ser incluso definidas stand alone collections, como por ejemplos beans que pueden ser un set o un map o una lista. Lo dejamos modo de cultura para que el lector investigue o haga googling en la gran cantidad de documentación que existe de Spring.

Gran parte de la configuración, independientemente de que puede ser hecha de un modo declarativo en el IoC Container, puede también ser combinada con anotaciones. Por ejemplo si queremos que una propiedad tenga que ser  obligatoriamente  evaluada podemos anotar sus métodos setter con @Required. Como un detalle, para que las anotaciones sean reconocidas tiene que estar un tag en el fichero de configuración tal y como indica la siguiente porción del fichero de configuración.

Hasta este punto del tutorial era necesario establecer los métodos setter en cada una de las propiedades para que tuviera lugar la inyección de código teniendo en cuenta lo establecido los ficheros de configuración. Es justo señalar que esta tarea era bastante engorrosa, unido a ser muy propicia para la generación de errores en aquellos desarrolladores que no programamos con Ides de desarrollo ni Plugins. Como solución tenemos el Auto-Wiring, una opción que nos permite entre otras cosas estar el NO tener que establecer una infinidad de referencias en el fichero de configuración para que luego puedan ser inyectadas en el código.
Es este un tema que analizaremos a fondo sobre todo porque lo utilizaremos en todo momento.Es importante entender el porqué de las cosas,podríamos trabajar sin Auto-Wiring en SPRING pero veamos que implica:
De manera general cuando un Bean necesita una referencia de otro esta referencia puede ser establecida especificando la referencia explícitamente:

<bean id="sequenceGenerator"
class="com.ldg.spring.sequence.SequenceGenerator">
<property name="prefixGenerator" ref="datePrefixGenerator" />
</bean>

Lo mismo se aplicaría si por ejemplo nuestro bean tuviera un constructor:

1
<constructor-arg ref="datePrefixGenerator" />

Imaginemos en un fichero de configuración de una aplicación real, en el que existen un gran número de referencias de un bean en otros ,sería mejor en ese caso que el Ioc Container pueda referenciar los Beans automáticamente y nos ahorraría los problemas de configurar el contenedor manualmente. De todo lo anterior se deriva esta necesidad de implementar el Auto-Wiring, que puede ser hecho también de manera declarativa o a través de anotaciones.
Para aligerar este breve tutorial haremos una breve referencia al modo Auto-Wiring de modo declarativo pero nos centraremos en el Auto-Wiring a través de anotaciones.

Distintas vías para realizar autowire de modo declarativo












 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<beans ...>
    <bean id="sequenceGenerator"
        class="com.ldg.spring.sequence.SequenceGenerator"
        autowire="byType">
        <property name="initial" value="100000" />
        <property name="suffix" value="A" />
    </bean>
    <bean id="datePrefixGenerator" class="com.ldg.spring.sequence.DatePrefixGenerator">
          &alt;property name="pattern" value="yyyyMMdd" />
    </bean>
</beans>

El ejemplo de configuración anterior es un autowire byType y en él Spring intentará hacer un wire con un bean que sea del mismo tipo o como es lógico del tipo de una interfaz por el bean implementada.En com.ldg.spring.sequence.SequenceGenerator tendrán que existir variable(s) de tipo  com.ldg.spring.sequence.DatePrefixGenerator   y en com.ldg.spring.sequence.DatePrefixGenerator tendrán que existir getter y setter de las correspondientes propiedades definidas en el bean.

El término usado propiamente hablando sería datePrefixGenerator será wired (enlazado,conectado,inyectado) automáticamente. Esto tiene desventajas en el caso que existieran más beans que fuesen del mismo tipo,en ese caso Spring no sabría con que bean hacer el wire. Un análisis que en su conjunto escapa al alcance de este articulo, si el lector quiere profundizar puede ir a la documentación de Spring, sobre todo dado el caso que tenga un marcado interés por el autowire de modo declarativo, tal y como indica el anterior esquema.

Autowire a través de anotaciones. Ya conocemos lo que es un autowire ,ahora veremos como definirlo a través de las anotaciones: @Autowire,Spring ó @Resource ,Java 1.5+. :
para que tengan efecto estas anotaciones en el código hemos de registrar una instancia de AutowiredAnnotationBeanPostProcessor en el IoC container lo cual puede ser hecho de la siguiente forma:

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">

ó de un modo más simple podría ser incluyendo el elemento context:annotation-config en el fichero de configuración de nuestro bean:

1
2
3
4
5
6
7
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:annotation-config />
    ... 
</beans>

La anotación @Autowired puede ser aplicada a una propiedad en particular para que Spring la inyecte. En la siguientes lineas de código anotamos el método setter de una propiedad con @Autowired y a su vez Spring intentará inyectar un bean cuyo tipo es compatible con el tipo de la propiedad en cuestión.

1
2
3
4
5
6
7
8
9
package com.ldg.spring.sequence;
import org.springframework.beans.factory.annotation.Autowired;
public class SequenceGenerator {
    ...
    @Autowired
    public void setPrefixGenerator(PrefixGenerator prefixGenerator) {
        this.prefixGenerator = prefixGenerator;
 } 
}

Dado el caso que tengamos un bean como el siguiente definido en el IoC container,será inyectada la propiedad indicada en el código anterior:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<beans ...>
    ...
    <bean id="sequenceGenerator"
        class="com.ldg.spring.sequence.SequenceGenerator">
        <property name="initial" value="100000" />
        <property name="suffix" value="A" />
    </bean>
    <bean id="datePrefixGenerator" class="com.ldg.spring.sequence.DatePrefixGenerator"> 
 <property name="pattern" value="yyyyMMdd" />
    </bean>
</beans>

Todas las propiedades anotadas con @Autowired han de ser enlazadas (wired), dado el caso que Spring no encuentre un bean a inyectar  se lanzará una exception ya que todas las propiedades anotadas con Autowired son requeridas.Otra cosa bien distinta es el hecho de que le indiquemos que no es requerida @Autowired(required = false) y en ese caso sino encuentra un bean que inyectar dejará la variable si setear.
Existen varías vías para realizar el proceso de autowire incluso sin necesidad de establecer @Autowire a los métodos setters en cuestión.Todas estas distintas vías escapan este articulo a pesar de que podríamos tratarlo en versiones futuras.

Como último aspecto de este articulo trataremos el Escanear Componentes  desde el classpath. Ello con lo que hemos visto hasta ahora puede ser hecho en Spring de un modo más rudimentario declarando cada uno de los componentes en el fichero de configuración del Ioc Container. Existe una vía para hacer esto de una manera mas eficiente que es a través del component scanning. El cual automáticamente escanea ,detecta e instancia aquellos componentes que estén en nuestro classpath y que tengan determinadas anotaciones. La principal anotación para que Spring pueda reconocer los componentes es @Component , a partir de este estereotipo encontraremos otros más específicos que serán tratados en posteriores entradas:
  • @Repository,@Controller,@Service para mas detalle ir a la api de Spring .       
1
2
3
4
5
6
7
8
9
package com.ldg.spring.sequence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SequenceService {
@Autowired
    private SequenceDao sequenceDao;
... 
}

1
2
3
...
SequenceService sequenceService = (SequenceService) context.getBean("sequenceService");
...

1
2
3
4
5
6
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:component-scan base-package="com.ldg.spring.sequence" />
</beans>

Respecto al código anterior ,donde quiera que encuentre una declaración de un objeto del tipo SequenceDao, que pertenezca al package "com.ldg.spring.sequence", lo inyectará en dicha variable ó lo que podríamos decir,que será inicializado el objeto.Para reconocer el objeto y poder registrarlo necesita la anotación @Component o algunos de sus estereotipos (@Repository, @Service, @Controller o cualquier otra anotación personalizada por el desarrollador) y para poder realizar la inyección necesitará el @Autowire.

En el fichero de configuración de los beans es importante destacar que usaremos el tag context:annotation-config:  para activar las anotaciones aplicadas en los bean que ya han sido registrados.
Mientras que el tag context:component-scan realiza la función de context:annotation-config  y además escanea los packages indicados para registrar los  beans en el application context.

A continuación mostramos 3 combinaciones para poder inyectar beans en código :

Aquí no se necesita anotaciones en el código,solo establecer los setter adecuados en el mismo :

1
2
3
4
5
6
<bean id="schoolBean" class="com.ldg.spring.beans.Schoolbean">
    <property name="teacherBean" ref="teacherBean"></property>
    <property name="studentBean" ref="studentBean"></property>
</bean>
<bean id="teacherBean" class="com.ldg.spring.beans.Teacherbean"></bean>
<bean id="studentBean" class="com.ldg.spring.beans.Studentbean"></bean>

Aquí necesitamos anotar con @Autowire todos aquellos métodos donde queremos inyectar los beans:

1
2
3
4
<context:annotation-config />
<bean id="schoolBean" class="com.ldg.spring.beans.Schoolbean" />
<bean id="teacherBean" class="com.ldg.spring.beans.Teacherbean" />
<bean id="studentBean" class="com.ldg.spring.beans.Studentbean" />

Aquí necesitamos anotar con @Autowire todos aquellos métodos donde queremos 
inyectar cada bean en cuestión y además necesitamos anotar con @Component 
aquellos objetos que queremos sean tenidos en cuenta en el momento que se 
escanee el/los paquete/s donde se encuentran dichos objetos.

Esta es según mi punto de vista la opción más eficiente :

<context:component-scan base-package="com.ldg.spring.beans" />

Un muestra de lo anteriormente explicado lo tenemos en el siguiente proyecto maven que te lo puedes descargar en mi github el proyecto SpringConfig.


Hemos intentado hacer una entrada lo mas resumida posible con uno de los temas claves de Spring,la inyección de código, aquí hay solo nociones.Han quedado algunos muchos elementos por ver, entre los que encontramos las anotaciones @Qualifier, @Required,@Resource  y que sería muy útil profundizar en ello http://projects.spring.io/spring-framework/.



Nos vemos en la siguiente entrega . . . . . . .