Pid 00275869
Pid 00275869
State Transfer
(REST)
PID_00275869
Ninguna parte de esta publicación, incluido el diseño general y la cubierta, puede ser copiada,
reproducida, almacenada o transmitida de ninguna forma, ni por ningún medio, sea este eléctrico,
mecánico, óptico, grabación, fotocopia, o cualquier otro, sin la previa autorización escrita
del titular de los derechos.
© FUOC • PID_00275869 REpresentational State Transfer (REST)
Índice
Introducción............................................................................................... 5
Objetivos....................................................................................................... 6
Resumen....................................................................................................... 49
Bibliografía................................................................................................. 51
© FUOC • PID_00275869 5 REpresentational State Transfer (REST)
Introducción
Objetivos
REpresentational State Transfer (REST) define una arquitectura de cómo imple- Sobre REST, SOAP y RMI
mentar servicios web distribuidos de forma más simple que otras arquitectu-
REST: REpresentational State
ras existentes como pueden ser Simple Object Access Protocol (SOAP) o Remote Transfer es un estilo de servi-
Method Invocation (RMI). cios web basados en HTTP.
SOAP: Simple Object Access Pro-
tocolo es un estilo de servicios
web que hace un uso extensi-
REST usa los métodos de HyperText Transfer Protocol (HTTP)1 para invocar las vo del lenguaje XML.
operaciones Create, Read, Update y Delete CRUD (en español, Crear, Leer, Actua- RMI: Remote Method Invoation
es un mecanismo para invocar
lizar y Borrar) en vez de definir operaciones específicas como se hace en otros objetos remotos en lenguaje
Java.
mecanismos de invocación remota de operaciones (por ejemplo, SOAP o RMI).
Esto quiere decir que, cuando en un servicio basado en REST se quiere definir
una operación de consulta de un recurso, en vez de definir una operación con (1)
Internet�Engineering�Task
Force�(IETF) (2014) Hypertext
el nombre consultaRecurso donde se pasa el código del recurso como pará-
Transfer Protocol (HTTP/1.1),
metro, se define una Uniform Resource Locator de acceso al recurso con el mé- RFC 7230 a 7235, <https://
[Link]/html/rfc7230>
todo HTTP GET, como por ejemplo [Link]/recurso/codigo2. <[Link]
rfc7235>
En este caso concreto, el parámetro se pasa en la URL, pero se pueden usar
diferentes mecanismos y/o formatos para el paso de parámetros. El resultado (2)
Nota general: ninguno de los
de esta operación se enviará dentro de un mensaje de respuesta HTTP y puede enlaces incluidos en el texto lleva
tener diferentes formatos, como veremos más adelante en este módulo. guiones de separación
(3)
Finalmente, hay que destacar que REST no es un estándar, a pesar de que es- World�Wide�Web�Consortium
(W3C) (2006). Extensible Markup
tá basado en estándares como por ejemplo HTTP, eXtensible Markup Language
Language (XML) 1.1 (Second Edi-
(XML)3 o Javascript Object Notation (JSON)4. A lo largo de este módulo veremos tion), <[Link]
xml11>
cómo usar estos estándares para ofrecer servicios web basados en REST.
(4)
European�Computer�Ma-
1.1. Visión general nufacturers�Association�(EC-
MA) (2017). The JSON (Javas-
cript Object Notation) Data In-
Como ya se ha dicho, REST no es un estándar. Se trata más bien de un estilo ar- terchange Syntax ECMA – 404
Standard, <[Link]
quitectural o patrón de diseño de una Interfaz de Programación de Aplicacio- [Link]/publications/fi-
les/ecma-st/[Link]>
nes (API, de sus siglas en inglés Application Programming Interface) que funciona
sobre HTTP. Lo definió inicialmente Roy Fielding en su tesis doctoral en 2000.
Referencia bibliográfica
Para entender mejor el funcionamiento de REST, explicaremos brevemente el Fielding,�R. (2000). Architec-
tural Styles and the Design of
funcionamiento del protocolo HTTP. HTTP es un protocolo de tipo Cliente –
Network-based Software Archi-
Servidor donde cliente y servidor se comunican mediante mensajes de peti- tectures. [en línia]: <https://
[Link]/~fiel-
ción (del cliente hacia el servidor) y de respuesta (del servidor hacia el cliente) ding/pubs/ disserta-
con un formato predeterminado, tal y como se muestra en la figura 1. tion/fielding_dissertation.pdf>.
© FUOC • PID_00275869 8 REpresentational State Transfer (REST)
HTTP/1.1 200 OK
Content-Length: 2000
Así pues, REST usa los mecanismos proporcionados por HTTP para poder im-
plementar servicios web. El estilo arquitectural de REST tiene algunas caracte-
rísticas específicas que detallamos a continuación:
• No�tiene�estado: cada petición del cliente hacia el servidor tiene que con-
tener toda la información necesaria para entender la petición y no puede
aprovechar el contexto almacenado en el servidor.
En las secciones siguientes se explica con más detalle cómo REST usa HTTP
para enviar y recibir datos y gestionar recursos usando las operaciones CRUD.
Los métodos HTTP que se usan en una API REST son los que aparecen en la
tabla 1. En la tabla 1 se presentan los métodos HTTP utilizados en REST, la
operación CRUD a la cual corresponde y una pequeña descripción de lo que
tiene que hacer la operación que usa cada método.
PATCH Partial Update – Actualización Se tiene que utilizar para modificar un recur-
parcial so, sin enviarlo entero, solo enviando los da-
tos que se tienen que modificar. Es parecido
a PUT, pero tiene que contener instrucciones
que indiquen qué datos del recurso original se
tienen que modificar.
En la tabla 2 se describen los posibles códigos de respuesta para cada una de las Referencia bibliográfica
operaciones de la tabla 1. Estos códigos corresponden a códigos de protocolo
Internet�Engineering�Task
HTTP, tal como se definen en Internet Engineering Task Force (2014). Force�(IETF) (2014). Hy-
pertext Transfer Protocol
(HTTP/1.1), RFC 7230 a
Tabla 2. Posibles códigos de respuesta HTTP a cada operación REST
7235. [en línea]: <https://
[Link]/html/rfc7230>
Método Código de respuesta correcta Código de respuesta errónea
y <[Link]
html/rfc7235>.
POST 201 Recurso creado 404 Recurso no encontrado
409 Conflicto, el recurso ya existe
Así pues, uno de los conceptos más relevantes dentro de REST es el recurso.
Cualquier información a la cual se puede dar un nombre es un recurso: un do-
cumento o imagen, un servicio temporal (por ejemplo, «el tiempo durante los
próximos tres días en Barcelona»), una colección de otros recursos, un objeto
no virtual (por ejemplo, una persona), etc. De este modo, un concepto que se
pueda representar como una referencia a un hipertexto puede ser un recurso.
Los recursos se pueden agrupar en colecciones, donde cada colección puede
contener varios recursos desordenados. Las colecciones también son recursos
por si mismas.
© FUOC • PID_00275869 12 REpresentational State Transfer (REST)
Como ya hemos visto en los ejemplos, las API REST usan Uniform Resource
Identifiers (URI) para acceder a los recursos. El diseñador de una API REST tie-
ne que definir un modelo de recursos que sea comprensible para los desarro-
lladores de sus clientes potenciales. Cuando a los recursos se les dan nombres
con lógica, una API es intuitiva y fácil de utilizar. Si se hace mal, esta misma
API puede ser difícil de usar y entender.
Referencia bibliográfica
Directrices�para�la�definición�de�URI�para�los�recursos�de�una�API
REST Internet�Engineering�Task
Force�(IETF) (2005). Uniform
Resource Identifier (URI):
1) Usar nombres (cosas) en vez de verbos (acciones) para definir los re- Generic Syntax, RFC 3986,
<[Link]
cursos. Los nombres tienen una característica que los verbos no tienen,
rfc3986>.
como son los atributos. Algunos ejemplos de nombres pueden ser usua-
rios del sistema, cuentas de usuario, dispositivos de red, etc. Dentro de
los nombres podemos distinguir entre recursos únicos (en singular) y
colecciones (en plural).
Ejemplos:
[Link]
[Link]
gestion-dispositivos/dispositivos-gestionados
[Link]
gestion-dispositivos/dispositivos-gestionados/{ID}
Ejemplos:
Jerarquía
[Link]
gestion-dispositivos/dispositivos-gestionados
[Link]
gestion-dispositivos/dispositivos-gestionados/{ID}
[Link]
gestion-dispositivos/dispositivos-gestionados
[Link]
gestion-dispositivos/dispositivos-gestionados/
HTTP://[Link]/mi-carpeta/mi-doc
[Link]
[Link]
[Link]
gestion-dispositivos/dispositivos-gestionados
[Link]
gestion-dispositivos/[Link]
Ejemplos:
Ejemplos:
[Link]
gestion-dispositivos/dispositivos-gestionados
[Link]
gestion-dispositivos/dispositivos-gestiona-
dos?region=cat
[Link]
gestion-dispositivos/dispositivos-gestiona-
dos?region=cat&fecha=2020-03-18
URL
Los datos se pueden enviar en la misma URL de petición. Así, cuando ha-
blamos de recursos concretos dentro de colecciones, podemos usar identifi-
cadores para referirnos a un recurso concreto. En un ejemplo anterior, he-
mos usado la colección clientes para referirnos a los clientes de una enti-
dad bancaria. El URI /clientes identifica la colección entera, es decir, todos
los clientes. La manera de identificar un único cliente sería un URI del tipo
/clientes/{clientID}, donde tenemos que dar un identificador de clien-
te para hacer la petición en el campo {clientID}. El URI resultante sería /
clientes/1111111H, donde se piden los datos del cliente identificado por
el identificador 11111111H, que corresponde a un documento nacional de
identidad (DNI).
Hay diferentes mecanismos para enviar los datos dentro del cuerpo del men-
saje de petición:
--73532303139
Content-Disposition: form-data; name="file3"; filename="[Link]"
Content-Type: image/jpeg
Datos binarios aquí en formato base64
--73532303139--
Host: [Link]
En esta petición GET podemos ver que no hay ningún contenido en el mensaje
(el método GET no lo permite) y que se acepta que la respuesta sea en formato
JSON (aplicación/json). También se puede ver el servidor a quien hacemos
la petición.
Esta petición PUT es muy parecida a la petición POST. Vemos que se envían
los datos completos del cliente, cambiando el valor 3 que había en POST por
un 1. Esto hará que se modifique todo el recurso en el servidor.
Esta petición DELETE contiene los datos del recurso que se tiene que borrar en
la URL. En este caso, se quiere borrar al cliente con id 1234. No hay contenido
del mensaje.
{
"Id": 12345,
"Cliente": "Arnau Sola",
"Cantidad": 3,
"Precio": 10.00
}
Los más habituales son ficheros en formato JSON o XML, que son los que
aparecen en el ejemplo. En la primera línea se indican ambos formatos, en la
segunda línea solo JSON, y en la tercera solo XML. En una petición solo se
envía una cabecera Accept, a pesar de que puede contener más de un valor,
como se ve en el primer ejemplo.
HTTP/1.1 200 OK
Content-Length: 19
Content-Type: application/json
{"success":"true"}
En este ejemplo se responde con el código que indica que la petición ha ido
bien. Además, encontramos dos cabeceras que indican la longitud y el tipo
de contenido. Finalmente, está el contenido del mensaje, que también indica
que la petición ha funcionado correctamente. En este caso los datos se envían
en formato JSON, con una única pareja nombre/valor dentro del objeto con
un valor de tipo booleano.
HTTP/1.1 200 OK
Content-Type: application/json
{
"público": {
"alumnos": "delegados",
"asignaturas": "todas",
"profesores": "todos"
},
"privado": {
"yo": "perfil",
"asignaturas": "XAI"
}
}
En este ejemplo se responde con el código que indica que la petición ha ido
bien. En este caso, se devuelven datos en formato JSON referentes a objetos
asociados a asignaturas, profesores y alumnos. En este caso hay dos objetos,
uno llamado «público» y otro llamado «privado», que contienen varios pa-
res de objetos nombre/valor. Todos los valores son de tipo cadena de caracteres.
HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
<?xml version="1.0" encoding="utf-8"?>
<Response>
<ResponseCode>0</ResponseCode>
<ResponseMessage>Success</ResponseMessage>
</Response>
© FUOC • PID_00275869 21 REpresentational State Transfer (REST)
En este ejemplo se responde con el código que indica que la petición ha ido
bien, y los datos se devuelven en formato XML. Este formato está explicado
con más detalle en el apartado «eXtensible Markup Language (XML)».
(6)
eXtensible Markup Language (XML) (World Wide Web Consortium, 2006) es World Wide Web Consortium
6 (W3C),<[Link]
un formato estandarizado por W3C , que describe cómo tienen que ser los [Fecha de consulta: marzo de
documentos XML. Estos documentos están formados por unidades de alma- 2020]
definiendo el marcaje (markup, en inglés) y otros definiendo los datos. El mar- XML deriva de SGML, que
caje codifica una descripción de la distribución del almacenamiento del docu- quiere decir Generalized Mar-
kup Language. Por definición,
mento, como también la estructura lógica. Con XML se proporciona un me- los documentos XML son con-
formes a SGML.
canismo para poder imponer restricciones tanto a la distribución como la es-
tructura lógica de los datos.
La figura 3 muestra la relación entre los diferentes elementos XML que apare-
cen en el ejemplo.
© FUOC • PID_00275869 22 REpresentational State Transfer (REST)
En este caso, hemos visto que la respuesta tiene formato XML. También sería
posible recibir una respuesta en formato JSON como en el ejemplo con el mé-
todo POST visto en el apartado «Javascript Object Notation (JSON)».
(7)
Los otros servicios web muy utilizados han sido los basados en el Simple Object World Wide Web Consortium
7 (W3C) (2007). Simple Object
Access Protocol (SOAP) . SOAP es un estándar del World Wide Web Consor- Access Protocol (SOAP) Versión
tium (W3C), que define un marco de trabajo basado en XML para comunicar 1.2, <[Link]
soap12/>
procesos remotos. Tanto los mensajes que se intercambian como el mecanismo
para definir el servicio usan XML para el envío y la descripción de los datos.
En este apartado hacemos un pequeño resumen de SOAP y otras tecnologías
relacionadas y comparamos sus características con los servicios web REST.
En SOAP los mensajes entre cliente y servicio web siempre se envían en for-
mato XML. A continuación se describen algunas de las características de los
servicios SOAP, como el envío de peticiones y respuestas o cómo se definen
las operaciones de un servicio.
Dentro del mensaje SOAP podemos ver que hay un elemento <Header> que
contiene un subelemento que indica que el tiempo máximo para responder
a la petición es de 10.000 y que todos los nodos que procesen esta petición
SOAP tienen que entender esta cabecera, tal como se indica con el atributo
mustUnderstand. En caso de que un nodo no lo entienda, devolverá un SOAP
Fault y no se continuará con el procesamiento del servicio web.
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="[Link]
<soap:Header>
<m:tempsMax value="10000" xmlns:m="[Link]
mustUnderstand="true"/>
</soap:Header>
<soap:Body xmlns:m="[Link]
<m:PrecioAccion>
<m:NombreAccion>Inditex</m:NombreAccion>
</m:PrecioAccion>
</soap:Body>
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: nnn
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="[Link]
<soap:Body xmlns:m="[Link]
<m:RespuestaPrecioAccion>
<m:Preu>34.5</m:Precio>
</m:RespuestaPrecioAccion>
</soap:Body>
</soap:Envelope>
Ahora que ya hemos visto cómo viajan tanto la petición como la respuesta
de un servicio web SOAP dentro de los mensajes del protocolo HTTP, expli-
caremos con algo más de detalle cómo se tienen que definir las operaciones
del servicio, el formato de los parámetros y respuestas del servicio y también
cómo se asocia este servicio a un protocolo de nivel de aplicación concreto,
en este caso, HTTP.
© FUOC • PID_00275869 25 REpresentational State Transfer (REST)
Web Services Description Language (WSDL) 2.0 es una recomendación del Sobre WSDL
W3C que describe un lenguaje basado en XML para describir servicios web.
World�Wide�Web�Consor-
Para hacerlo se define un modelo abstracto de qué es lo que ofrece el servicio. tium�(W3C)(2007). Web Ser-
Además, se definen los criterios de conformidad para los documentos descri- vices Description Language
(WSDL) Versión 2.0, <https://
tos en este lenguaje. [Link]/TR/wsdl20/>
(8)
• types. Contiene la especificación de los tipos de datos intercambiados en- World�Wide�Web�Consor-
tium�(W3C)(2012). XML Schema
tre el cliente y el servicio web. Por defecto, estos tipos de datos se definen
Definition Language (XSD) 1.1,
con un XML Schema8. <[Link]
ma11-1/>
xmlns:xs= "[Link]
targetNamespace= "[Link]
xmlns= "[Link]
<xs:element name="PeticionPrecioAccion" type="tipoPrecioAccion"/>
<xs:complexType name="tipoPrecioAccion">
<xs:sequence>
<xs:element name="NombreAccion" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="RespuestaPrecioAccion" type="tipoRespuestaPrecioAccion"/>
<xs:complexType name="tipoRespuestaPrecioAccion">
<xs:sequence>
<xs:element name="Precio" type="xs:float"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</types>
<interface name = "PrecioAccionInterface" >
<operation name="PrecioAccion"
pattern="[Link]
style="[Link]
wsdlx:safe = "true">
<input messageLabel="In" element="stns:PeticionPrecioAccion" />
<output messageLabel="Out" element="stns:RespuestaPrecioAccion" />
</operation>
</interface>
<binding name="PrecioAccionSOAPBinding"
interface="tns:PrecioAccionInterface"
type="[Link]
wsoap:protocol="[Link]
wsoap:mepDefault="[Link]
<operation ref="tns:PrecioAccion"/>
</binding>
<service
name ="ServicioPrecioAccion"
interface="tns:PrecioAccionInterface">
<endpoint name ="PrecioAccionEndpoint"
binding ="tns:PrecioAccionSOAPBinding"
address ="[Link]
</service>
</description>
Los elementos del WSDL están relacionados entre ellos. Por ejemplo, los atri-
butos interface y binding del elemento service son los elementos
que interface y binding (que coinciden con los valores definidos en el
atributo name), respectivamente. El elemento operation dentro de la bin-
ding (en este caso sólo hay uno, pero podría haber más) coinciden con el
© FUOC • PID_00275869 27 REpresentational State Transfer (REST)
Los valores tns y stns que hay delante de algunos de los nombres corres-
ponden a las referencias a los espacios de nombres donde se definen los di-
ferentes elementos. La referencia a los espacios de nombres la encontramos
normalmente en el elemento raíz del documento XML, en este caso concreto,
en description.
xmlns= "[Link]
xmlns:tns= "[Link]
xmlns:stns = "[Link]
xmlns:wsoap= "[Link]
xmlns:wsdlx= "[Link]
Para comparar estos dos tipos de servicios web, nos fijaremos en algunas de
sus características principales:
Como se puede ver, la petición hecha con REST, donde solo es necesaria la
URL, es mucho más simple tanto desde el punto de vista de la cantidad de
datos enviados como del procesamiento de estas que la de SOAP, donde se
envían muchos elementos XML que no son relevantes para el servicio.
Los mensajes de respuesta pueden ser igual de complejos en los dos tipos de
servicio web, puesto que REST puede enviar cualquier tipo de fichero, incluso
en formato XML. La diferencia principal es que SOAP solo acepta XML, y REST
puede aceptar diferentes tipos de datos.
También hemos visto que SOAP define las características de sus servicios (for-
mato de los mensajes de envío y respuesta, tipo de envío utilizado, protoco-
lo de nivel de aplicación, dirección del servicio, etc.) en un WSDL. ¿Se po-
dría hacer esto mismo con REST? La respuesta es que sí, en la versión 2.0 de
WSDL. La manera de hacerlo es en el elemento binding, donde podemos in-
dicar que usamos el tipo de binding correspondiente a HTTP con http://
[Link]/ns/wsdl/http y como operación del servicio un método HTTP,
como por ejemplo, GET (whttp:method="GET"). A continuación veamos un
ejemplo de cómo podría ser un elemento binding que defina estos datos para
un servicio REST modelo.
<wsdl:binding name="ServeiHTTPBinding"
type="[Link]
interface="tns:InterfazServicio">
<wsdl:operation ref="tns:Servicio" whttp:method="GET"/>
© FUOC • PID_00275869 29 REpresentational State Transfer (REST)
</wsdl:binding>
(9)
Desde el punto de vista de la seguridad, REST funciona sobre HTTP, que sopor- Internet�Engineering�Task
Force�(IETF)(2018). The Trans-
ta autenticación básica y seguridad en la comunicación mediante Transport
port Layer Security (TLS) versión
Layer Security (TLS)9. En cambio, SOAP tiene el WS-SECURITY10, que es un 1.3,<[Link]
rfc8446>.
estándar que define toda una serie de mecanismos de seguridad para servicios
web. (10)
Organization�for�the
Advancement�of�Structu-
red�Information�Standards
Conclusiones de los servicios REST y SOAP
(OASIS)(2006). Web Services
Security: SOAP Message Secu-
rity 1.1 (WS-Security), <https://
En este apartado, hemos visto que los servicios web SOAP y REST comparten
[Link]/commit-
algunas características, como por ejemplo el uso de HTTP como protocolo pre- tees/[Link]/16790/
wss-v1.1-spec-os-
ferido para el envío de sus datos y otras bastante diferentes como son los for- [Link]>.
matos de envío de las peticiones y respuestas. Este último punto ha hecho que
los servicios web basados en REST sean los más utilizados actualmente. La fle-
xibilidad que proporcionan con peticiones mucho más simples o la no obliga-
ción de usar un formato como XML han permitido que este tipo de servicios se
hayan expandido y que sea posible procesarlos fácilmente con cualquier tipo
de dispositivo, especialmente desde dispositivos móviles. Además, la posibili-
dad de recibir solo una parte de los datos e ir enlazando con el resto a través de
URL también les permite gestionar la transferencia de datos más fácilmente.
© FUOC • PID_00275869 30 REpresentational State Transfer (REST)
(11)
El lenguaje Java proporciona una especificación llamada JAX-RS, definida en Oracle Corporation (2014).
The Java Tutorial, Annotations,
el documento JSR 311 (Sun Microsystems, 2008). Esta especificación define
<[Link]
cómo el lenguaje Java da soporte a los servicios web basados en REST. En esta javase/tutorial/java/annota-
tions/[Link]>.
especificación se describe cómo acceder a los recursos, definiendo anotaciones
Java11, que apuntan a clases de tipo recurso, a métodos HTTP y a parámetros
Referencia bibliográfica
y resultados a los llamamientos a los métodos HTTP.
Sun�Microsystems
(2008). JAX-RS: Java™
En la tabla 4 se describen algunas de las anotaciones utilizadas en JAX-RS y API for RESTful Web Ser-
vices. [en línia]: <https://
una pequeña descripción de estas12. [Link]/
otn-pub/jcp/jaxrs-1.0-fr-
eval-oth-JSpec/jaxrs-1.0-fi-
Tabla 4. Cómo enviar las peticiones según el método HTTP utilizado [Link]>.
Anotación Descripción
@Path La clase raíz de acceso a un recurso con lenguaje Java ha de tener Las anotaciones Java
esta anotación para indicar en qué URL se puede encontrar este re-
curso. Ejemplo: @Path ("/hola") la dirección base de nuestro
Las anotaciones en el lenguaje
recurso será [Link] Esta anotación también se de programación Java tienen
puede encontrar dentro de los métodos, y entoncesel valor que ha- el formato (@nombre), donde
ya dentro de la anotación se concatenará en el @Path original. el símbolo @ indica al compila-
dor Java que lo que encontrará
@método_HTTP Cada método HTTP tiene su propia anotación. Así, podemos en- es una anotación.
contrar @POST, @GET, etc. Esta anotación dentro del código del Una anotación es un metadato
servicio REST indica con qué método HTTP responderemos a una sintáctico que se puede aplicar
operación concreta. a una clase, método u otros
elementos de este lenguaje.
@tipoParam Las anotaciones acabadas en Param nos indican cómo se pueden
recibir los parámetros. Así, QueryParam indica que se reciben en
la parte de la query de la URL, después del símbolo ?, FormParam (12)
Oracle Corporation (2013).
que se reciben dentro del cuerpo del mensaje con la clave de for-
Java Enterprise Edition 7
mato - valor o PathParam que son parte de la URL (se identifican
Specification APIs, <https://
dentro de corchetes {} en la anotación @Path correspondiente a ese
[Link]/javaee/7/api/
método).
[Link]>
@Consumes, @Produces Estas dos anotaciones indican qué datos se reciben (@Consumes) y
cuáles se devuelven (@Produces). Dentro de estas anotaciones, se
debe colocar el tipo MIME correspondiente. Ejemplos: applica-
tion/json o text/html. La clase Java MediaType define algu-
nos de estos tipos de datos.
Lo primero que encontramos en el servicio son las clases JAX-RS que usaremos
dentro de nuestra clase Java, que se denomina «hola». Los nombres de los
paquetes (packages, en inglés) Java empiezan con [Link], que identifica
la biblioteca Java (javax) que implementa servicios web (ws) basados en REST
(rs).
Las clases que incluimos son algunas de las que se corresponden con las ano-
taciones que han aparecido en la tabla 4. Tenemos el Path, los métodos GET y
POST, los tipos de parámetros FormParam, PathParam y QueryParam y Con-
sumes y Produces. También tenemos la clase del subpaquete core, MediaTy-
pe, que permite identificar los tipos de datos dentro de Consumes y Produces.
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Path("hola")
public class hola {
/* Métodos Java que responden a GET y a POST */
}
@GET
@Produces(MediaType.TEXT_HTML)
public String getHtml() {
return "<html><head/><body>GET</body></html>";
}
@GET
@Path("/get")
@Produces(MediaType.TEXT_HTML)
public String getQuery(@QueryParam("nom") String nombre) {
return "<html><head/><body>"+nombre+"</body></html>";
}
@GET
@Path("/get/{nombre}")
@Produces(MediaType.TEXT_HTML)
public String getPath(@PathParam("nombre") String nombre) {
return "<html><head/><body>"+nombre+"</body></html>";
}
@POST
@Consumes("application/x-www-form-urlencoded")
@Produces(MediaType.TEXT_HTML)
public String postHtml(@FormParam("nombre") String nombre) {
return "<html><head/><body>"+nombre+"</body></html>";
}
En este formulario tenemos que indicar la URL del servicio (atributo action,
[Link] el método de envío (atributo method, en
este caso tiene que ser POST) el tipo de codificación de los datos (atributos
enctype, application/x-www-form-urlencoded) y dentro del formulario
debe haber un campo que se llame nombre. En este caso, es un campo de tipo
texto y el atributo name tiene el valor nombre, que es el valor esperado por
el servicio. Si no lo definimos exactamente así, el mensaje HTTP enviado no
coincidirá con el que espera el servicio y la petición fallará. En las figuras 8 y
9 encontramos el formulario y la respuesta dada por el servicio.
Figura 8. Formulario
Hay que destacar que lo que hemos visto hasta ahora es independiente del
tipo de servidor con el cual se trabaje, puesto que se trata de una especificación
Java que los diferentes fabricantes pueden implementar a su manera.
Para crear un servicio con JAX-RS, hay que crear una clase que amplíe la cla-
se abstracta Application (dentro del paquete [Link]). En esta
clase se tiene que definir el recurso raíz del servicio y registrar las clases que
responden a los diferentes métodos HTTP. Para el servicio que se ha creado en
el apartado 2, la clase derivada de Application podría ser la siguiente:
import [Link];
import [Link];
@[Link]("app")
public class ApplicationConfig extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new [Link]<>();
[Link]([Link]);
return resources;
}
}
© FUOC • PID_00275869 35 REpresentational State Transfer (REST)
En esta clase se está definiendo la raíz del servicio (app) y se añade la clase
[Link], que implementa las operaciones del servicio del apartado 2, a
los recursos disponibles en dicho servicio.
@METODO_HTTP
@Path("/URL_Access/{PATH_PARAM}")
@Consumes(TIPOS_MIME_PETICION)
@Produces(TIPOS_MIME_RESPUESTA)
public String nomMetodo(@XParam("nombreParam") String nombreParam) {
return <MENSAJE EN FORMATO TIPOS_MIME_RESPUESTA>;
}
La forma más general que hay de responder a una petición REST con JAX-RS
es la de tener una anotación de método HTTP. A continuación, podemos tener
una anotación con un @Path específico para este método, que puede contener
(o no, es opcional) uno o varios parámetros de tipo @PathParam, rodeados por
«{}». Pueden aparecer en cualquier posición dentro del path, como por ejem-
plo {param1}/path/{param2}. Cada parámetro de este tipo aparecerá como
parámetro del método, y será del tipo @PathParam. También podemos tener
parámetros del tipo @QueryParam (los enviados en la sección de consulta de
la URL) o @FormParam, en caso de que el tipo MIME de solicitud sea appli-
cation/x-www-form-urlencoded o multipart/form-data. Hay que de-
cir que podríamos llegar a encontrar los tres tipos de parámetros en un mismo
método.
Hemos denominado Item a esta clase de soporte. Contiene una serie de ano-
taciones Java para que se haga el tratamiento automático del lenguaje XML.
Las anotaciones son @XmlRootElement, que identifica el elemento raíz del
© FUOC • PID_00275869 36 REpresentational State Transfer (REST)
import [Link];
import [Link];
import [Link];
import [Link];
@XmlRootElement(name="item")
@XmlAccessorType([Link])
public class Item {
@XmlElement
private int id;
@XmlElement
private String name;
public int getId() {
return id;
}
public void setId(int id) {
[Link] = id;
}
public String getName() {
return name;
}
public void setName(String name) {
[Link] = name;
}
@Override
public String toString(){
return "Id: " + [Link] + " Nombre: " + [Link];
}
© FUOC • PID_00275869 37 REpresentational State Transfer (REST)
En el primer método, el que trabaja con XML, hay que destacar que ahora re-
cibimos un parámetro de tipo Item en el método, que convierte automática-
mente los datos XML en campos de la clase Java. En este caso, el resultado en
XML se genera dentro del mismo método, pero aquí podríamos añadir todo
tipo de tratamiento de datos XML, almacenamiento en otros soportes (fichero
a disco, base de datos, reenvío a otros servicios, etc.).
@PUT
@Path("/xml")
@Consumes("application/xml")
@Produces("application/xml")
public String putXML(Item i) {
String resultado;
resultado = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><item><id>"
+([Link]()+1)+"</id><name> "
+ [Link]() +" Perez</name></item>";
return resultado;
}
(13)
En el segundo método, el que trabaja con JSON, la estrategia es un poco Biblioteca�Java�de�Gson,
<[Link]
diferente. Como parámetro recibimos un [Link], que con-
gle/gson> [Fecha de consulta:
tiene un canal de acceso a los datos JSON enviados por la aplicación clien- marzo de 2020]
te. Con este Inputstream, utilizando una clase Java de soporte a JSON
([Link])13, conseguimos un objeto de tipo Item, que des-
pués modificamos para enviar la respuesta al cliente. Lo mismo que se ha co-
mentado para el caso XML (bases de datos, disco, etc.) se podría hacer aquí,
realizando el tratamiento correspondiente de los datos JSON. Hay muchas li-
brerías Java de apoyo a la creación, la lectura y la escritura de datos JSON. Se
ha elegido esta por su simplicidad de uso.
@PUT
@Path("/json")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String putJSON([Link] is) {
Item test;
[Link] gson = new [Link]();
[Link] reader = new [Link]
(new [Link](is));
test = [Link](reader, [Link]);
[Link] ([Link]()+1);
© FUOC • PID_00275869 38 REpresentational State Transfer (REST)
El segundo mensaje de solicitud contiene los mismos datos, pero ahora para
el formato JSON para la petición y la respuesta.
HTTP/1.1 200 OK
Content-Length: 95
© FUOC • PID_00275869 39 REpresentational State Transfer (REST)
Content-Type: application/xml
<?xml version="1.0" encoding="UTF-8"?>
<item>
<id>5</id>
<name>Camera photo</name>
</item>
El segundo mensaje de solicitud contiene los mismos datos, pero ahora para
el formato JSON para la petición y la respuesta.
HTTP/1.1 200 OK
Content-Length: 41
Content-Type: application/json
{
"id": 5,
"name": "Camera photo"
}
Invocar un servicio web basado en REST desde una aplicación cliente implica Referencia bibliográfica
abrir una conexión HTTP con el servicio y enviar una petición en el formato
March�Hermo,�M.�I. (2020).
esperado por el mismo (método HTTP, cabeceras y parámetros o datos). Esto Programación de sockets en Ja-
lo podríamos hacer con una conexión vía sockets o usando clases de soporte va. Barcelona: UOC.
En el resto del apartado se explicará con un algo más de detalle cómo imple- Referencia bibliográfica
mentar dos aplicaciones cliente, una aplicación Java de escritorio y una apli-
Java�Community�Pro-
cación web basada en J2EE. cess (2006). JSR 88: Ja-
vaTM EE (J2EE) Applica-
tion Deployment, <https://
[Link]/en/jsr/de-
tail?id=88&showPrint>
© FUOC • PID_00275869 40 REpresentational State Transfer (REST)
Oracle�Corporation
En este apartado se explicará cómo implementar un cliente de prue- (2017). Java Servlets Spe-
ba para nuestro servicio web basado en REST, pero la estrategia se- cification v4.0, <https://
[Link]/ser-
ría muy similar para conectarse a otro servicio REST ya existente. Pri- vlet-spec/downloads/ser-
vlet-4.0/servlet-4_0_FINAL.pdf>
mero veremos cómo hacerlo desde una aplicación web con un servlet
([Link]) y después con una aplicación Java de
escritorio.
Un servlet es una clase Java que puede responder a métodos HTTP hechos por
un navegador. En este sentido, es un poco como un servicio web REST, pero
limitado a GET y a POST y orientado a un usuario final. Ayuda en la recepción
de datos de formularios HTML y ficheros. También tiene acceso a la petición
HTTP que se recibe desde el cliente (en este caso, un navegador) y a la respuesta
HTTP que se tiene que devolver, que tiene que ser en lenguaje HTML para que
el navegador lo entienda.
La declaración de una clase de tipo servlet con apoyo para servicios web REST
podría ser como sigue:
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@WebServlet(name = "Client", urlPatterns = {"/Client"})
public class Client extends HttpServlet {
/* Métodos del servlet para contactar con el servicio */
}
En el código que vemos hay importación de todas las clases Java necesarias y
la declaración de la clase, que deriva de HttpServlet. Encontramos también
una anotación Java que nos indica que esto es un servlet (@WebServlet) y la
URL de acceso a este desde la aplicación web.
client = [Link]();
resultado = [Link](REST_URL)
.path("json")
.request(MediaType.APPLICATION_JSON)
.put([Link]("{\"id\":4,\"name\":\"camera\"}"),
[Link]);
}
Hay que destacar que el único problema que podemos encontrar en este caso
es el de disponer de todas las librerías Java que apoyen a una aplicación cliente
de servicio web basado en REST, puesto que la librería que contiene las clases
[Link] tiene bastantes dependencias con otras librerías Java
que cualquier entorno de programación puede resolver sin demasiado proble-
ma. No ponemos ninguna versión concreta, puesto que el lenguaje Java evo-
luciona tan rápidamente que enseguida quedarían obsoletas.
[Link] ([Link]());
}
}
}
© FUOC • PID_00275869 43 REpresentational State Transfer (REST)
3.1. Node. js
[Link] es un entorno de servidor de código abierto que funciona sobre dife- Sobre Node. js
rentes sistemas operativos y que usa el lenguaje Javascript en el servidor (el
OpenJS�Foundation,�Node.
uso habitual de Javascript se encuentra en el lado cliente, incluido en el na- js, <[Link]
vegador). [Fecha de consulta: marzo de
2020].
Para poderlo usar como servidor REST, hay que utilizar lo que se conoce como
(14)
IBM,�MEAN�(MongoDB
el conjunto de herramientas MEAN, que incluye las herramientas MongoDB,
ExpressJS�Angular�[Link])
ExpressJS, Angular y [Link] (MEAN)14. Todas estas herramientas se basan en stack explained, <https://
[Link]/cloud/learn/mean-
lenguaje Javascript. Como mínimo tenemos que tener [Link] y ExpressJs, stack-explained> [Fecha de consul-
ta: marzo de 2020]
pero para tener un servicio REST completo es recomendable tenerlas todas. A
continuación las describimos brevemente.
MongoDB�Inc.,
En el subapartado siguiente explicamos con algo más de detalle cómo imple- MongoDB, <https://
[Link]/es>. [Fe-
mentar un servicio web básico basado en REST con [Link]. cha de consulta: marzo de
2020].
StrongLoop,�Inc.,�ExpressJS,
3.1.1. Desarrollo de una API REST con Node. JS y ExpressJS <[Link]
[Fecha de consulta: marzo de
2020].
Para desarrollar un servicio REST con [Link] hay que instalarlo desde su web Google,�Angular, <https://
oficial. Una vez instalado, hay que instalar también ExpressJS para poder ofre- [Link]/>. [Fecha de con-
sulta: marzo de 2020].
cer las diferentes operaciones vía web.
Una vez estas dos herramientas están instaladas, implementar una API básica
es bastante sencillo.
Lo primero que hay que hacer es declarar las dependencias que tendrá nuestra
API. Esto se puede hacer con el código Javascript siguiente:
Aquí se indica que hay dos dependencias, express y body-parser, que usa-
remos después. A continuación declaramos la variable app que será la aplica-
ción web que usará Express.
A continuación vemos una operación que ofrece esta API. Dada una letra, de-
vuelve como resultado la misma letra en mayúsculas. Si ya es mayúscula, de-
vuelve la misma letra que ha escrito el usuario. La URL de acceso (que se tiene
que concatenar a la URL del servicio) tiene la forma /letras/a y el resultado
que devuelve es {"resultado":"A"}.
3.2. Python
incluso servicios basados en REST. Para hacerlo, necesita un entorno web, co- Python�Software�Founda-
mo por ejemplo Flask o Django. En los ejemplos siguientes usaremos Flask tion, Python. [en línea]:
<[Link]
para el soporte web. [Fecha de consulta: marzo de
2020]
Pallets.�Flask. [en
Flask es un framework web escrito en lenguaje Python. Se le denomina micro- línea]: <https://
framework porque no necesita herramientas o librerías extra para su funcio- [Link]/
en/1.1.x/> [Fecha de consul-
namiento. Aun así, se pueden añadir extensiones fácilmente para proporcio- ta: marzo de 2020]
nar funcionalidad extra. Django�Software
Foundation. Django.
[en línea]: <https://
[Link]/>
Django es otro framework web escrito en Python. Es gratuito y de código abier-
[Fecha de consulta: marzo de
to, y sigue el modelo arquitectural Model-Template-View (MTV). 2020]
Django�Software�Founda-
tion. Model-Template-View
En el subapartado siguiente explicamos con algo más de detalle cómo imple- (MTV) architectural model in
Django. [en línea]: <https://
mentar un servicio web básico basado en REST con Python. [Link]/
en/3.0/ faq/general/> [Fecha
de consulta: marzo de 2020]
3.2.1. Desarrollo de una API REST con Python y Flask
Para desarrollar un servicio REST con Python hay que instalarlo desde su web
oficial. Una vez instalado, hay que instalar también Flask para poder ofrecer
las diferentes operaciones vía web.
Una vez estas dos herramientas están instaladas, implementar una API básica
es bastante sencillo.
Lo primero que hay que hacer es declarar las dependencias que tendrá nuestra
API. Esto se puede hacer con el código Python siguiente:
Las dependencias que tenemos son Flask, jsonify y request. Todas estas
dependencias provienen de Flask. Esto se indica en from Flask. Después
declaramos la variable app, que contendrá nuestra aplicación web. Por último,
declaramos la variable cuentas, que contendrá los datos de una cuenta ban-
caria en formato JSON.
© FUOC • PID_00275869 47 REpresentational State Transfer (REST)
@[Link]("/cuentas", methods=["GET"])
def getCuentas():
return jsonify(cuentas)
@[Link]("/cuentas/<id>", methods=["GET"])
def getCuenta(id):
id = int(id) - 1
return jsonify(cuentas[id])
La última operación responde al método POST y nos permite dar de alta una
nueva cuenta. La URL de acceso será /cuenta y los datos se moverán en for-
mato JSON al cuerpo del mensaje HTTP. Por último, la aplicación web se inicia
en el puerto 8080.
@[Link]("/cuenta", methods=["POST"])
def addCuenta():
nombre = [Link]['nombre']
balance = [Link]['balance']
datos = {'nombre': nombre, 'balance': balance}
[Link](datos)
return jsonify(datos)
if __name__=='__main__':
[Link](port=8080)
app = Flask(__name__)
cuentas = [
{'nombre': "Anna", 'balance':450.0},
{'nombre': "Pau", 'balance':250.0},
]
@[Link]("/cuentas", methods=["GET"])
def getCuentas():
return jsonify(cuentas)
@[Link]("/cuentas/<id>", methods=["GET"])
def getCuenta(id):
id = int(id) - 1
return jsonify(cuentas[id])
@[Link]("/cuenta", methods=["POST"])
def addCuenta():
nombre = [Link]['nombre']
balance = [Link]['balance']
datos = {'nombre': nombre, 'balance': balance}
[Link](datos)
return jsonify(datos)
if __name__=='__main__':
[Link](port=8080)
© FUOC • PID_00275869 49 REpresentational State Transfer (REST)
Resumen
Hemos visto también la comparación entre los servicios web basados en SOAP
y REST, incidiendo en las características de cada uno y explicando algunas de
las diferencias principales entre ellos.
Bibliografía
Django Software Foundation. Django. [en línea]:<[Link] [Fe-
cha de consulta: marzo de 2020].
Fielding, R. (2000). Architectural Styles and the Design of Network-based Software Architectures.
[en línea]:<[Link]
IBM. MEAN (MongoDB Express Angular Node) stack explained. [en línea]:<https://
[Link]/cloud/learn/mean-stack-explained> [Fecha de consulta: marzo de 2020].
Internet Engineering Task Force (IETF) (2005). Uniform Resource Identifier (URI): Ge-
neric Syntax, RFC 3986. [en línea]:<[Link]
Internet Engineering Task Force (IETF) (2015). Returning Values from Forms: multi-
part/form-data, RFC 7578. [en línea]:<[Link]
Internet Engineering Task Force (IETF) (2018). The Transport Layer Security (TLS) Pro-
tocol Versió 1.3. [en línea]:<[Link]
Java Community Process (2006). JSR 88: JavaTM EE (J2EE) Application Deployment. [en
línea]:<[Link]
Sun Microsystems (2008). JAX-RS: Java™ API for RESTful Web Services. [en línea]:<https://
[Link]/otn-pub/jcp/jaxrs-1.0-fr-eval-oth-JSpec/[Link]>.
World Wide Web Consortium (W3C) (2006). Extensible Markup Language (XML) 1.1
(Second Edition). [en línea]:<[Link]
World Wide Web Consortium (W3C) (2007). Simple Object Access Protocol (SOAP)
Versión 1.2. [en línea]:<[Link]
World Wide Web Consortium (W3C) (2007). SOAP Version 1.2 Part 2: Adjuncts (Second
Edition). [en línea]:<[Link]
World Wide Web Consortium (W3C) (2007). Web Services Description Language
(WSDL) Versión 2.0. [en línea]:<[Link]
World Wide Web Consortium (W3C) (2012). XML Schema Definition Language (XSD)
1.1. [en línea]:<[Link]