Spring mvc. Servicios Rest respondiendo en Json o XML

4
38010

Spring mvc. Servicios Rest respondiendo en Json o XML

0. Índice de contenidos.

1. Introducción

En este tutorial vamos a ver las configuraciones necesarias para que un servicio Rest, bajo Spring mvc devuelva XML o Json en función del accept de la cabecera de la petición.

Para devolver XML o Json tenemos varias opciones pero la más elegante me parece tener un solo servicio Rest mapeado en una sola URL, y que en función de lo que quiera el cliente ( accept en la cabecera de la petición ) se sirva una cosa u otra.


2. Entorno

  • Hardware: Portátil MacBook Pro 15′ (2.0 GHz Intel i7, 8GB DDR3 SDRAM, 500GB HDD).
  • AMD Radeon HD 6490M 256 MB
  • Sistema Operativo: Mac OS X Snow Leopard 10.6.7
  • Software relacionado con el tutorial: Eclipse Helios, Spring 3.1.1.RELEASE, Apache Tomcat 7


3. Configurando los servicios Rest con Spring mvc

Lo primero de todo es configurar el web.xml.

		


			rest

			
				org.springframework.web.context.ContextLoaderListener
			
		
			
				Spring configuration file
				contextConfigLocation
				
					classpath:applicationContext-model.xml,
					WEB-INF/applicationContext-servlet.xml
				
			
			
			
				webAppRootKey
				rest
			
		
			
				applicationContext
				org.springframework.web.servlet.DispatcherServlet
				1
			
		
			
				applicationContext
				/rest/*
			
	
  • En la línea 4 estamos declarando el listener de Spring responsable de levantarnos nuestros contextos.
  • En las líneas 7-14 definimos los applicationContext que queremos levantar. Luego los veremos más en profundidad.
  • En las líneas 21-30 declaramos en Servlet de forma estándar. Según la declaración que hacemos la configuración del Servlet se espera en un archivo con el nombre «applicationContext-servlet.xml», es decir, nombre del Servlet seguido de -servlet.xml (estándar). Lo estamos mapeando contra /rest/*, es decir
    todas las llamadas del tipo localhost:8080/rest/rest/* serán tratadas por este Servlet.

Vamos a ver ahora la configuración del Servlet, que la tenemos como ya hemos dicho en applicationContext-servlet.xml

¿Sencillo verdad? Aún así siempre me gusta explicarlo todo para que quede clarito y por si alguien tiene alguna duda.

  • En la línea 10 indicamos a Spring que vamos a utilizar anotaciones, y que queremos que nos instancie las clases que tengamos anotadas, por ejemplo, con @Controller.
  • En la línea 12 le decimos a partir de que paquete tiene que escanear en busca de clases anotadas.

A continuación vamos a crearnos un controlador con el soporte de Spring mvc para que gestione las peticiones. Lo vemos a continuación.

		
			
			
			
	

Como veis hemos declarado un controlador al que le llegarán las peticiones del tipo http://localhost:8080/rest/rest/rrhh/. Aquí podemos meter una serie de métodos relacionadas con la gestión de personal que normalmente llamarán a servicios que tengamos alojados en nuestro modelo y devolverán una respuesta.

Si lo que queremos es una respuesta Json o XML dependiente de la cabecera de la petición no podemos utilizar el atributo «produces» de la anotación @RequestMapping para indicar que este método devuelve application/json ó application/xml. Lo que tenemos que hacer es lo siguiente:

  • 1º. Insertamos la siguiente dependencia en el pom de nuestro módulo web donde tenemos definido el controlador. Es necesaria para poder ofrecer la respuesta en Json.
  • 			
    				org.codehaus.jackson
    				jackson-mapper-asl
    				1.6.4
    			
    		
  • 2º. En nuestra entidad Person, tendremos que definir los elementos del XML que queramos que aparezan. Lo vemos a continuación.
		package com.autentia.tutoriales.entities;
		import javax.persistence.Entity;
		import javax.persistence.GeneratedValue;
		import javax.persistence.Id;
		import javax.xml.bind.annotation.XmlElement;
		import javax.xml.bind.annotation.XmlRootElement;
							
		@XmlRootElement
		@Entity
		public class Person {
									
			@Id
			@GeneratedValue
			private int id;
								
			@XmlElement
			private final String name;
								
			public Person(String name) {
				this.name = name;
			}
								
			public String getName() {
				return name;
			}
								
			public int getId() {
				return id;
			}
		}
	

Como podeis ver hemos anotado la clase como raíz del XML con @XmlRootElement y los atributos que queremos que aparezan en el XML los anotamos con @XmlElement

Esta clase la tengo en otro módulo que es el que he definido como model en el proyecto. Si os acordais en el web.xml definiamos el applicationContext-model que corresponde precisamente a este módulo. Os lo pego a continuación para tener todas las piezas del puzzle.

		

			

			
			
				
					
						com.autentia.tutoriales.entities
					
				
			

			
	


4. Probando los distintos tipos de respuesta

Nos vamos a crear un cliente sencillito en HTML que haga 2 peticiones al servidor, una que tenga en el accept de la cabecera «application/json» y la otra «application/xml». El código fuente del cliente os lo pongo a continuación:

		
			
				
				
			
			
			
				TUTORIAL SERVICIOS REST JSON/XML
				

JSON

XML

Estamos incluyendo 2 javascripts, el primero es jquery,
que os lo podeis bajar de: http://code.jquery.com/jquery-1.7.2.min.js
El segundo es un javascript muy cortito cuyo código os pongo a continuación :

		function jsonPerson() {
			var url = "http://localhost:8080/rest/rest/rrhh/person/";
			$.getJSON(url,null);
		}
	

Si pinchamos en JSON, podemos ver en los detalles de la petición el Accept

Si ahora nos vamos a la respuesta tendremos lo siguiente:

{«name»:»Respuesta en formato dependiente del header de la petición»,»id»:0}

que es el Json que representa al objeto que hemos creado.

Si repetimos el proceso pulsando en XML en la respuesta nos vendrá lo siguiente:

		 
		 
			Respuesta en formato dependiente del header de la petición 
		
	

Por último comentar que si quisieramos forzar un formato en concreto
podríamos anotar el método de la siguiente forma:
@RequestMapping(value = «/person/», method = RequestMethod.GET, produces=»application/json»). Esto devolvería siempre json.


5. Conclusiones

Me parece muy útil tener un servicio que responda en distintos formatos según lo que acepte el cliente y a nivel de código queda muy limpio al tenerlo en un solo método. Espero que os haya sido útil el tutorial. Un saludo.


6. Información sobre el autor

Alberto Barranco Ramón es Ingeniero Técnico en Informática de Gestión y Graduado en Ingeniería del Software por la Universidad Politécnica de Madrid

Mail: abarranco@autentia.com.

Twitter: @barrancoalberto

Autentia Real Business Solutions S.L. – «Soporte a Desarrollo».

Consultor tecnológico de desarrollo de proyectos informáticos.
Ingeniero técnico en informática de gestión y graduado en ingeniería del software por la Universidad Politécnica de Madrid.
Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación.
Somos expertos en Java/Java EE

4 COMENTARIOS

  1. Hola Alberto,
    Bueno tutorial, un ejemplo muy sencillo con el que verlo muy claro. Me ha gustado ver lo fácil que es hacer que el servicio funcione con XML o JSON.
    Sin embargo te ha faltado mencionar un detalle que a mi me ha hecho perder un poco de tiempo hasta que he encontrado el problema, y es que no has comentando nada de que para usar las anotaciones @Xml* de la entidad Person es necesario usar la JDK 1.6. Yo suelo todavía usar por defecto la 1.5 y por eso me fallaba.

    Salu2.

  2. Enhorabuena, muy buen post. Una pregunta, el archivo pom al que te refieres, es un XML que se debe crear sólo con esa información o debe incluir algo más?

    Muchas gracias

  3. Hola jest, el pom.xml es el archivo de configuración de maven, en concreto para este módulo sería:

    4.0.0

    parent
    com.autentia.tutoriales
    1.0-SNAPSHOT

    com.autentia.tutoriales
    rest
    1.0-SNAPSHOT
    war
    rest Maven Webapp
    http://maven.apache.org

    com.autentia.tutoriales
    model
    1.0-SNAPSHOT

    org.springframework
    spring-web
    ${spring.version}

    org.springframework
    spring-webmvc
    ${spring.version}

    javax.servlet
    servlet-api
    2.5
    provided

    org.codehaus.jackson
    jackson-mapper-asl
    1.6.4

    rest

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad