You are on page 1of 59

Cliente rico con ExtJS y REST

Ricardo Borillo Domenech


borillo@uji.es
Índice


REST:

Introducción

Jersey JAX-RS

Acceso a servicios REST

Testing en Jersey

Cliente rico:

Tipos de frameworks

ExtJS

Integración ExtJS / REST
Introducción

Principales objetivos:

Arquitectura flexible e interoperable:
Modelo de negocio siempre accesible a
distintos frameworks en distintos
dispositivos

Facilidad de integración con otras
aplicaciones

Mejora de la experiencia de usuario
Introducción

¿Qué es REST?
Introducción

REST = Representational State Transfer:



Define un estilo de arquitectura distribuida basada en
el protocolo HTTP y que explota el uso enlaces o
hypermedia (al igual que la WWW)

No está ligado al formato ni a la estructura de los
documento intercambiados (JSON, XML, PDF, HTML
… cualquier formato)

Orientado al acceso a recursos y colecciones

Las URIs son su elemento más importante
Introducción


Una URI define la identidad de un recurso en la web

Tanto las URL como los URN son URIs

Un URN sólo define un nombre, pero no ninguna
forma de recuperar ese recurso
(urn:isbn:0451450523)

Una URL define como recuperar ese recurso a través
de la web (http://www.a.com/doc.pdf)
Introducción

Petición HTTP:

GET /recurso/base?param=valor HTTP/1.1


Host: www.uji.es
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; es-CL; rv:1.9.2.10) Gecko/20100922
Ubuntu/10.10 (maverick) Firefox/3.6.10
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: es-cl,es;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Introducción

Respuesta HTTP:

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html
Connection: Keep-Alive
Keep-Alive: timeout=30, max=999
Server: Oracle-Application-Server-10g/10.1.2.3.0 Oracle-HTTP-Server OracleAS-
Web-Cache-10g/10.1.2.3.0 (H;max-age=3600+360;age=350;ecid=759620335360,0)
Content-Length: 25671
Date: Thu, 14 Oct 2010 17:05:03 GMT
Introducción

Otros aspectos fundamentales:



Cookies

Códigos de respuesta HTTP:

Informational 1xx (100 Continue, 101 Switching protocols)

Successful 2xx (200 OK, 201 Created, 202 Accepted, 204 No Content)

Redirection 3xx (301 Moved Permanently, 302 Found, 304 Not
Modified

Client Error 4xx (400 Bad Request, 401 Unauthorized, 403 Forbidden,
404 Not Found, 405 Method Not Allowed)

Server Error 5xx (500 Internal Server Error, 501 Not Implemented, 502
Bad Gateway, 503 Service Unavailable)
Introducción

¿Pero esto no es la web tal y como la


conocemos?
Introducción


REST aprovecha realmente la arquitectura
diseñada para la WWW

Los navegadores sólo aprovechan una parte de
la semántica disponible
Introducción


POST. Creación de un nuevo recurso
No es seguro y no es idempotente

GET. Recuperación de un recurso
Sí es seguro y sí es idempotente

PUT. Modificación de un recurso o creación de un
recurso del que conocemos el ID
No es seguro y sí que es idempotente

DELETE. Borra un recurso
No es seguro y sí que es idempotente
Introducción

Ejemplos:

GET /cars: Lista todos los coches

GET /cars/1234AAW: Recupera un coche

POST /cars: Añade un nuevo coche

PUT /cars/1234AAW: Crea o modifica un
coche

PUT /cars/1234AAW: Crea un nuevo coche.

DELETE /cars/1234AAW: Elimina un coche
Introducción

¿Los servicios REST son Web Services? ¿En


qué se diferencian REST y SOAP?
Introducción

Wikipedia:

”Web services are typically application
programming interfaces (API) or Web APIs that
are accessed via Hypertext Transfer Protocol
(HTTP) and executed on a remote system
hosting the requested services. Web services
tend to fall into one of two camps: SOAP Web
services or RESTful Web services.”
Introducción

Inconvenientes del stack ws-*:



Es complejo y difícil de mantender (generación de código a
partir de documentos WSDL)

Necesidad de un framework complejo

Problemas de interoperabilidad entre frameworks y plataformas

Problemas para ser usados desde dispositivos móviles y
aplicaciones RIA basadas en JavaScript

Sólo sirve para XML (con adjuntos binarios)

No aprovecha al 100% la arquitectura HTTP al ser definido con
soporte independiente del transporte
Introducción


La clave es HATEOAS:
Hypermedia as the Engine of Application State

Diferencia a REST de un RPC convencional y
representa un avance:
”Las respuestas del servidor contienen links
que corresponden a las acciones que se
pueden realizar, en función del estado actual
de la aplicación”
Introducción

Código ejemplo HATEOAS:


{

'home': {

'description':'go to system home',

'href':'/store/home'

}, 'search': {

'description':'search books',

'href':'/store/books{?title,author,minPrice,maxPrice}'

}, 'byId': {

'description':'get book by id',

'href':'/store/books/{bookId}'

}
Índice


REST:

Introducción

Jersey JAX-RS

Acceso a servicios REST

Testing en Jersey

Cliente rico:

Tipos de frameworks

ExtJS

Integración ExtJS / REST
Jersey JAX-RS


Jersey es la implementación Java de referencia
del estándar JAX-RS para la definición de
servicios REST:

https://jersey.dev.java.net/


Se aplica sobre POJOs

Define un conjunto de anotaciones, de
proveedores y de filtros para gestionar el ciclo
de vida de las peticiones/respuestas HTTP
Jersey JAX-RS

Anotaciones básicas para definir recursos y


operaciones:

@GET, @PUT, @POST, @DELETE

@Path

@Path("coches")
public class CochesService {
@GET
public List<Coche> getCoches() {
}
}
Jersey JAX-RS

Acceso a parámetros en las URLs:



@PathParam

@QueryParam

@GET
@Path("/coches/{matricula}")
public Coche getCoche(
@PathParam("matricula") String matricula,
@QueryParam("puertas") @DefaultValue("5")
String puertas) {
}
Jersey JAX-RS

Identificación del tipo de contenido recibido o


emitido:

@Consumes. Tipo mime esperado.

@Produces. Tipo mime producido

@GET
@Produces(MediaType.APPLICATION_XML)
public List<Coche> getCoches() {
}

@PUT
@Consumes(MediaType.APPLICATION_JSON)
public void updateCoche(Coche coche) {
}
Jersey JAX-RS

Petición HTTP:
@GET @Path @QueryParam
GET /recurso/base?param=valor HTTP/1.1
Host: www.uji.es @PathParam
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; es-CL; rv:1.9.2.10) Gecko/20100922
Ubuntu/10.10 (maverick) Firefox/3.6.10
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: es-cl,es;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate @Produce
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Jersey JAX-RS

Respuesta HTTP:
Response
HTTP/1.1 200 OK
@Produce
Content-Type: text/html
Server: Oracle-Application-Server-10g/10.1.2.3.0
Content-Length: 25671
Date: Thu, 14 Oct 2010 17:05:03 GMT

<html> Contenido de la respuesta



</html>
Jersey JAX-RS

Distintas serializaciones disponibles para


distintos formatos:

XML/JSON mediante JAXB

”natural” JSON mediante Jackson

ATOM mediante Apache Abdera

Lectura/escritura personalizada en función del tipo
mime gracias a los interfaces MessageBodyReader
y MessageBodyWriter
Jersey JAX-RS

Disponibles filtros tanto en el cliente como en el


servidor para:

Autenticar peticiones o realizar conexiones
seguras

Registrar las peticiones en un fichero de log

Transformar datos de entrada o de salida

Cualquier otro filtro personalizado
Jersey JAX-RS

Otros módulos/funcionalidades disponibles:



Mapeo de excepciones Java a respuestas y
códigos HTTP mediante ExceptionMapper

Integración con Spring Framewok

API para simplifica el acceso cliente (Jersey Client)

Gestión de uploads (Jersey Multipart)

Testing integrado (Jersey Test Framework)

Autorización mediante OAuth
Jersey JAX-RS


Configuración de la webapp:
<web-app>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.decharlas.usuarios.services</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
<param-value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Índice


REST:

Introducción

Jersey JAX-RS

Acceso a servicios REST

Testing en Jersey

Cliente rico:

Tipos de frameworks

ExtJS

Integración ExtJS / REST
Acceso a servicios REST

Distintos métodos de acceso:



Navegador:

Accediendo a URLs mediante GET y con el envío de formularios
mediante POST

Aplicaciones de cliente rico haciendo uso de AJAX
(XmlHttpRequest). Veremos el caso de ExtJS.

Ejemplo aplicaciones web que aprovechan la potencia de la
semántica REST:
http://www.thomas-bayer.com/restgate/index.do

Otros clientes de acceso:

curl

Jersey Client API
Acceso a servicios REST

Curl:

POST:
curl -i -H "Accept: application/json" -X POST -d "user=pepe"
http://localhost/persons/person

PUT:
curl -i -H "Accept: application/json" -X PUT -d
"phone=964556677" http://localhost/persons/person/1

GET:
curl -i -H "Accept: application/json"
http://localhost/persons?zipcode=93031

DELETE:
curl -i -H "Accept: application/json" -X DELETE
http://localhost/persons/person/1
Acceso a servicios REST

Jersey Client API:



Simplifica el acceso a los servicios REST
desde Java

Creación de un cliente y llamada GET:

Client client = Client.create();


WebResource resource =
client.resource("http://localhost/app/rest");
ClientResponse response =
resource.path("/coche/1").queryParam("matricula",
"1234546").get(ClientResponse.class);
Coche coche = response.getEntity(Coche.class)
Acceso a servicios REST

Jersey Client API:



Llamada de tipo POST:
MultivaluedMap<String, String> params = new
MultivaluedMapImpl();
params.putSingle("param1", "value1");
resource.path("/perico").type(MediaType.APPLICATION_FORM_URLEN
CODED).post(Persona.class, params);


Comprobación del resultado:
if (response.getStatus() == Status.OK.getStatusCode()) {
...
}
Índice


REST:

Introducción

Jersey JAX-RS

Acceso a servicios

Testing en Jersey

Cliente rico:

Tipos de frameworks

ExtJS

Integración ExtJS / REST
Testing en Jersey

Requisitos:

Entorno de integración contínua

API testeable

Independencia respecto al despliege de
la aplicación
Testing en Jersey

public class AllTests extends JerseyTest


{
public AllTests() throws Exception
{
super(new WebAppDescriptor.Builder("es.uji.jersey").
contextParam("contextConfigLocation",
"classpath:applicationContext.xml").
servletClass(SpringServlet.class).
contextListenerClass(ContextLoaderListener.class).build());
}

@Override
protected TestContainerFactory getTestContainerFactory()
{
return new EmbeddedGlassFishTestContainerFactory();
}

@Test
public void testHelloWorld()
{
WebResource webResource = resource();
String result = webResource.path("rest/helloworld").
accept(MediaType.TEXT_PLAIN).get(String.class);
Assert.assertEquals("Hello World", result);
}
}
Índice


REST:

Introducción

Jersey JAX-RS

Acceso a servicios

Testing en Jersey

Cliente rico:

Tipos de frameworks

ExtJS

Integración ExtJS / REST
Tipos de frameworks

Frameworks para aplicaciones web:



Frameworks para integración con contenido
HTML/CSS existente (jQuery, prototype, etc)

Frameworks para la creación de aplicaciones
ricas completas:

JavaScript: ExtJS, qooxdoo, SmartClient

No JavaScript: Flex, OpenLaszlo, JavaFX

Frameworks mixtos: Dojo, jQuery UI, Prototype
UI
Índice


REST:

Introducción

Jersey JAX-RS

Acceso a servicios

Testing en Jersey

Cliente rico:

Tipos de frameworks

ExtJS

Integración ExtJS / REST
ExtJS

Desarrollo de aplicaciones ricas


multiplataforma:

ExtJS. Framework de cliente rico para aplicaciones web.

Ext GWT. Integración de GWT con ExtJS.

Sencha Touch. Aplicaciones móbiles ricas para iPhone,
iPad y Android.

Ext Designer. Diseñador WYSIWYG para ExtJS.
ExtJS
ExtJS
ExtJS
ExtJS

Recursos imprescindibles para desarrollar con


ExtJS:

Ejemplos:
http://dev.sencha.com/deploy/dev/examples/

Documentación:
http://dev.sencha.com/deploy/dev/docs/

Foros:
http://www.sencha.com/forum/
Tipos de frameworks

Recursos imprescindibles para desarrollar con


ExtJS:

Videos:
http://www.extjs.tv/

Libros:

ExtJS in Action:
http://www.manning.com/garcia/

Learning ExtJS:
http://www.learningextjs.com/
Índice


REST:

Introducción

Jersey JAX-RS

Acceso a servicios

Testing en Jersey

Cliente rico:

Tipos de frameworks

ExtJS

Integración ExtJS / REST
Integración ExtJS / REST

Características interesantes que favorecen la


integración:

ExtJS implementa sus componentes de datos
siguiendo el patrón MVC

ExtJS soporta distintos formatos de datos
mediante la implementación de Readers

Los stores en ExtJS soportan desde la versión
3.0 el atributos ”restful”.

ExtJS se puede combinar con otros
frameworks como jQuery, Prototype o YUI
Integración ExtJS / REST

Elementos principales:

De estructura:

Viewport y Panel:
http://dev.sencha.com/deploy/dev/docs/index.html

Layouts:
http://dev.sencha.com/deploy/dev/examples/#sample-9

De datos:

Store

Reader/Writer (XML/JSON)

Comunicación AJAX
Integración ExtJS / REST

Elementos principales:

Widgets:

GridPanel:
http://dev.sencha.com/deploy/dev/examples/#sample-4

FormPanel y componentes de formulario:
http://dev.sencha.com/deploy/dev/examples/#sample-11

TreePanel:
http://dev.sencha.com/deploy/dev/examples/#sample-8

Windows:
http://dev.sencha.com/deploy/dev/examples/#sample-7
Integración ExtJS / REST

Otras funcionalidades interesantes:



Drag & Drop:
http://dev.sencha.com/deploy/dev/examples/#sample-14

Charts:
http://dev.sencha.com/deploy/dev/examples/#sample-6

Offline support:
http://dev.sencha.com/deploy/dev/examples/#sample-1
Integración ExtJS / REST

Múltiples formas de crear objetos:



Con el operador new:
var editor = new Ext.ux.grid.RowEditor({
saveText: 'Actualizar'
});


Con la inclusión implícita usando JSON y el
atributo ”xtype”:
{
xtype : 'form',
items: [{
xtype : 'textfield',
name : "nombre",
fieldLabel : 'Nombre'
}]
}
Integración ExtJS / REST

Aplicación mínima con ExtJS:


<html>
<head>
<link rel="stylesheet" type="text/css"
href="ext-3.3.0/resources/css/ext-all.css" />
<script type="text/javascript"
src="ext-3.3.0/adapter/ext/ext-base-debug.js"></script>
<script type="text/javascript"
src="ext-3.3.0/ext-all-debug.js"></script>

<script type="text/javascript">
       Ext.onReady(function() {
Ext.Msg.alert("Información", "Alerta desde ExtJS");
       });
</script>
</head>

<body></body>
</html>
Integración ExtJS / REST

Elementos necesarios para la creación de un


GridPanel en ExtJS:

Store. Responsable de la gestión de datos que recibe
de un Reader o que envía a un Writer.

Reader/Writer. Procesamiento de los datos de
entrada/salida en múltiples formatos (JSON, XML)
y accediento a múltiples destinos (memoria, HTTP).

GridPanel. Componente para la representación de
tablas de datos.
Integración ExtJS / REST

Store para el GridPanel:


new Ext.data.Store( {
    restful : true,
      url : '/usuarios/rest/users',
      reader : new Ext.data.XmlReader( {
         record : 'user',
         totalProperty : 'total',
         id : 'id'
      }, [ 'id', 'dni', 'nombre']),
writer : new Ext.data.XmlWriter({
writeAllFields : true,
xmlEncoding: "utf-8"
})
   });
Integración ExtJS / REST

GridPanel:
var grid = new Ext.grid.GridPanel( {

store : store,
sm : new Ext.grid.RowSelectionModel( { singleSelect : true }),
frame : true,
colModel : new Ext.grid.ColumnModel( {
 defaults : {
  sortable : true
 },
 columns : [ {
    header : 'Código',
    dataIndex : 'id',
    width : 10,
editor: {
xtype: 'textfield',
allowBlank: false
}
 }, … ]
}),
listeners : {                         
rowclick : function(grid, rowIndex, evt) {

}
}
});
Integración ExtJS / REST

Relación entre los datos, el store y el grid:


var grid = new Ext.grid.GridPanel( {
... <?xml version="1.0" encoding="UTF-8">
colModel : new Ext.grid.ColumnModel( { <users>
 defaults : { <user>
  sortable : true <id>1</id>
 }, <dni>123456780X</dni>
 columns : [ { <nombre>Perico 0</nombre>
    header : 'Código', </user>
    dataIndex : 'id',
...
    width : 10,
editor: { </users>
xtype: 'textfield',
allowBlank: false
}
 }, … ]
}), new Ext.data.Store( {
...     restful : true,
});       url : '/usuarios/rest/users',
      reader : new Ext.data.XmlReader( {
         record : 'user',
         totalProperty : 'total',
         id : 'id'
      }, [ 'id', 'dni', 'nombre']),
...
   });
Integración ExtJS / REST

FormPanel:
new Ext.FormPanel( {
title : 'Users',
frame : true,
url: '/usuarios/rest/users',
items : [ {
xtype : 'textfield',
name : "id",
fieldLabel : 'Código',
allowBlank: false
}, … ],
buttons: [ {
xtype : 'button',
text : 'Añadir',
handler : function() {
if (form.getForm().isValid()) {
form.getForm().submit({
success: function(form, action) {},
failure: function(form, action) {}
});
}
}
}]
});
Fin

¿Preguntas?

You might also like