A real systemwithjms-rest-protobuf-mongodb

1,846 views

Published on

Presentación utilizada en el Codemotion 2012 en Madrid.

Integración de un sistema Real utilizando Google Protobuf, Spring, REST, JMS y MongoDB

La experiencia de un proyecto real para control de tráfico marítimo, sus requisitos, las tecnologías que se utilizarón y el porqué de cada una de ellas.

Published in: Technology, Business
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,846
On SlideShare
0
From Embeds
0
Number of Embeds
22
Actions
Shares
0
Downloads
56
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

A real systemwithjms-rest-protobuf-mongodb

  1. 1. Integrando Sistemas reales con REST, JMS, Protobuf y MongoDB Andrés Perez Indra David Gómez Extrema Sistemaslunes 26 de marzo de 12
  2. 2. David G ómez iner ect & Tra Sw Archit om ema-sistemas.c dgomez@extr zg @dgome Andrés Pérez y David Gómez 2 Indra y Extrema Sistemaslunes 26 de marzo de 12
  3. 3. és Pérez Andr itect David G ómez iner Sw Arch ect & Tra Sw Archit om z@indra. es ema-sistemas.c apere dgomez@extr zg @dgome Andrés Pérez y David Gómez 2 Indra y Extrema Sistemaslunes 26 de marzo de 12
  4. 4. Hablaremos de • El caso real. • La arquitectura propuesta – Interfaz REST entre GUI y Server – Protobuf entre Dispositivos y Server/GUI – JMS para comunicación asíncrona Server -> GUI – MongoDB para persistencia Andrés Pérez y David Gómez 3 Indra y Extrema Sistemaslunes 26 de marzo de 12
  5. 5. El caso real. Control de tráfico marítimo Andrés Pérez y David Gómez 4 Indra y Extrema Sistemaslunes 26 de marzo de 12
  6. 6. El caso real. Control de tráfico marítimo Emisor AIX 3-5 min Andrés Pérez y David Gómez 5 Indra y Extrema Sistemaslunes 26 de marzo de 12
  7. 7. El caso real. Control de tráfico marítimo Emisor AIX 3-5 min Andrés Pérez y David Gómez 6 Indra y Extrema Sistemaslunes 26 de marzo de 12
  8. 8. El caso real. Control de tráfico marítimo Receptor GPS Radar (3 s) Goniometro Emisor AIX Estación Meteo, 3-5 min Cámaras, ... Andrés Pérez y David Gómez 6 Indra y Extrema Sistemaslunes 26 de marzo de 12
  9. 9. El Problema: La escalabilidad Andrés Pérez y David Gómez 7 Indra y Extrema Sistemaslunes 26 de marzo de 12
  10. 10. El Problema: La escalabilidad Por cada barco: Recepción y procesamiento de señales (nº) Transacciones, Cálculo de alarmas Gestión de Históricos Andrés Pérez y David Gómez 8 Indra y Extrema Sistemaslunes 26 de marzo de 12
  11. 11. El Problema: La escalabilidad Señales (1 AIS x 3 min + 1 radar x 3 seg) x 100 barcos Alarmas Persistencia de Líneas de Varada: (10.000+ ptos x 100+ líneas) 40 Alarmas Zonas, Elementos Navegación Persistencia: Total: 87 tablas + históricos(x2) Andrés Pérez y David Gómez 9 Indra y Extrema Sistemaslunes 26 de marzo de 12
  12. 12. El problema: la escablabilidad Andrés Pérez y David Gómez 10 Indra y Extrema Sistemaslunes 26 de marzo de 12
  13. 13. La arquitectura Speaker’s Name 11 Speaker mail – company or communitylunes 26 de marzo de 12
  14. 14. REST Cameras GUI 1 JMS Server Protobuf JMS Radar REST Spring Data GUI 2 DB Gonio Speaker’s Name 12 Speaker mail – company or communitylunes 26 de marzo de 12
  15. 15. REST Comunicación síncrona entre GUI y Servidor Speaker’s Name 13 Speaker mail – company or communitylunes 26 de marzo de 12
  16. 16. ¿Qué es REST? • REpresentational State Transfer • HTTP como protocolo de comunicación – No sólo como transporte • La sesión es responsabilidad del cliente – Escalable Andrés Pérez y David Gómez 14 Indra y Extrema Sistemaslunes 26 de marzo de 12
  17. 17. ¿Qué es REST? • URIs representan recursos (no acciones) • Acciones indicadas en el método HTTP • Formato especificado en cabeceras HTTP – Accept: – ContentType: • No todas las respuestas contienen datos • Error o Resultado con HTTPStatus Andrés Pérez y David Gómez 15 Indra y Extrema Sistemaslunes 26 de marzo de 12
  18. 18. Comparación Andrés Pérez y David Gómez 16 Indra y Extrema Sistemaslunes 26 de marzo de 12
  19. 19. Comparación GET http://server:port/zones/ POST http://server:port/zones/388 GET http://server:port/zones/388 PUT http://server:port/zones/388 Andrés Pérez y David Gómez 16 Indra y Extrema Sistemaslunes 26 de marzo de 12
  20. 20. Comparación GET http://server:port/zones/ POST http://server:port/zones/388 GET http://server:port/zones/388 PUT http://server:port/zones/388 http://server:port/listZones http://server:port/createNewZone http://server:port/getZone?id=388 http://server:port/updateZone?id=388 Andrés Pérez y David Gómez 16 Indra y Extrema Sistemaslunes 26 de marzo de 12
  21. 21. (Spring) REST en el servidor Andrés Pérez y David Gómez 17 Indra y Extrema Sistemaslunes 26 de marzo de 12
  22. 22. (Spring) REST en el servidor <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>3.0.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>3.0.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> <version>3.0.6.RELEASE</version> </dependency> Andrés Pérez y David Gómez 17 Indra y Extrema Sistemaslunes 26 de marzo de 12
  23. 23. ¿Por qué REST con Spring? • Simplifica – la gestión de serialización – La gestión de códigos de error – Mapping de URLs a métodos • En cliente tenemos el RestTemplate Andrés Pérez y David Gómez 18 Indra y Extrema Sistemaslunes 26 de marzo de 12
  24. 24. Un Controlador de Zona (I) Andrés Pérez y David Gómez 19 Indra y Extrema Sistemaslunes 26 de marzo de 12
  25. 25. Un Controlador de Zona (I) @Controller public  class  ZoneController  {     @Inject   private  ZoneService  service;   //  getZoneList  -­‐>  GET     @RequestMapping(value="/zones",  method=RequestMethod.GET)   public  @ResponseBody  List<Zone>  getZones(){     return  service.findAll();   }   //  newZone  -­‐>  POST   @RequestMapping(value  =  "/zones",  method  =  RequestMethod.POST)   @ResponseStatus(HttpStatus.CREATED)   public  void  newZone(@RequestBody  Zone  z,         HttpServletRequest  request,  HttpServletResponse  response)  {     service.save(z);     response.addHeader("Location",           getLocationForChildResource(request,  order.getId()));   } } Andrés Pérez y David Gómez 19 Indra y Extrema Sistemaslunes 26 de marzo de 12
  26. 26. Un Controlador de Zona (II) Andrés Pérez y David Gómez 20 Indra y Extrema Sistemaslunes 26 de marzo de 12
  27. 27. Un Controlador de Zona (II) @Controller public  class  ZoneController  {   //  newZone  -­‐>  POST   @RequestMapping(value  =  "/zones",  method  =  RequestMethod.POST)   @ResponseStatus(HttpStatus.CREATED)   public  void  newZone(@RequestBody  Zone  zone,         HttpServletRequest  request,  HttpServletResponse  response)  {     service.save(zone);     response.addHeader("Location",           getLocationForChildResource(request,  zone.getId()));   }   private  String  getLocationForNewResource(HttpServletRequest  request,  Object  identifier)  {     StringBuffer  url  =  request.getRequestURL();     UriTemplate  template  =  new  UriTemplate(url.append("/{zoneId}").toString());     return  template.expand(identifier).toASCIIString();   } } Andrés Pérez y David Gómez 20 Indra y Extrema Sistemaslunes 26 de marzo de 12
  28. 28. Un Controlador de Zona (III) Andrés Pérez y David Gómez 21 Indra y Extrema Sistemaslunes 26 de marzo de 12
  29. 29. Un Controlador de Zona (III) @Controller public  class  ZoneController  {   //  getZone  -­‐>  GET     @RequestMapping(value="/zones/{id}",  method=RequestMethod.GET)   public  @ResponseBody  Zone  getZone(@PathVariable("id")  String  id)  {     return  service.findById(id);   }       //  updateZone  -­‐>  PUT   @RequestMapping(value="/zones/{id}",  method=RequestMethod.PUT)   @ResponseStatus(HttpStatus.NO_CONTENT)   public  void  updateZone(@RequestBody  Zone  z)  {     service.save(z);   }   //  delete  -­‐>  DELETE     @RequestMapping(value="/zones/{id}",  method=RequestMethod.DELETE)   @ResponseStatus(HttpStatus.NO_CONTENT)     public  void  deleteZone(@PathVariable("id")  String  id){     service.removeById(id);   }   } Andrés Pérez y David Gómez 21 Indra y Extrema Sistemaslunes 26 de marzo de 12
  30. 30. Configuración Andrés Pérez y David Gómez 22 Indra y Extrema Sistemaslunes 26 de marzo de 12
  31. 31. Configuración <?xml  version="1.0"  encoding="UTF-­‐8"?> <beans  xmlns="http://www.springframework.org/schema/beans">   <context:component-­‐scan  base-­‐package="com.vts.server"/>   <bean  id="xstreamMarshaller"  class="org.springframework.oxm.xstream.XStreamMarshaller"/>   <mvc:annotation-­‐driven/> </beans> Andrés Pérez y David Gómez 22 Indra y Extrema Sistemaslunes 26 de marzo de 12
  32. 32. RestTemplate • Invocar servicios REST desde los GUI Andrés Pérez y David Gómez 23 Indra y Extrema Sistemaslunes 26 de marzo de 12
  33. 33. RestTemplate • Invocar servicios REST desde los GUI @Component public  class  RestZoneServiceInvoker  implements  ZoneServiceInvoker  {            /*  "http://"  +  serverHostName  +  "/vts-­‐server/vts/zones"  */   private  String  baseURI;       private  RestTemplate  restTemplate;   @Inject   public  RestZoneServiceInvoker(RestTemplate  restTemplate)  {     this.restTemplate  =  restTemplate;   }     @Override   public  void  createNew(Zone  z)  {     URI  uri  =  restTemplate.postForLocation(baseURI,  z);   } } Andrés Pérez y David Gómez 23 Indra y Extrema Sistemaslunes 26 de marzo de 12
  34. 34. RestTemplate • RestTemplate implements RestOperations Andrés Pérez y David Gómez 24 Indra y Extrema Sistemaslunes 26 de marzo de 12
  35. 35. RestTemplate • RestTemplate implements RestOperations public  interface  RestOperations  {   <T>  T  getForObject(String  url,  Class<T>  responseType,   Object...  uriVariables)  throws  RestClientException;   HttpHeaders  headForHeaders(String  url,  Object...  uriVariables)   throws  RestClientException;   URI  postForLocation(String  url,  Object  request,  Object...  uriVariables)   throws  RestClientException;   <T>  T  postForObject(String  url,  Object  request,   Class<T>  responseType,  Map<String,  ?>  uriVariables) void  put(String  url,  Object  request,  Object...  uriVariables)   throws  RestClientException;   void  delete(String  url,  Object...  uriVariables)   throws  RestClientException; ... } Andrés Pérez y David Gómez 24 Indra y Extrema Sistemaslunes 26 de marzo de 12
  36. 36. Protobuf Comunicación entre dispositivos y servidor/GUI .Net/C++/Java Speaker’s Name 25 Speaker mail – company or communitylunes 26 de marzo de 12
  37. 37. Protobuf. 2011-05-01. v 2.4.1 Necesidades en la integración de módulos • Soluciones analizadas en la integración de módulos • Funcionamiento de la solución Andrés Pérez y David Gómez 26 Indra y Extrema Sistemaslunes 26 de marzo de 12
  38. 38. ¿qué necesitamos? • Sencillez • Alto rendimiento • Adaptabilidad • Compatibilidad con las distintas tecnologías de desarrollo – Controladores de dispositivos en C++ – Servidor central y clientes en Java – Otros componentes sw (Servidores de video) en .Net Andrés Pérez y David Gómez 27 Indra y Extrema Sistemaslunes 26 de marzo de 12
  39. 39. ¿REST? REST, XML (Servidor java <-> Cliente java) • Pros: – Sencillez. Ampliamente extendido – Compatible con las tecnologías propuestas – Adaptabilidad • Contras: – rendimiento insuficiente para dispositivos Andrés Pérez y David Gómez 28 Indra y Extrema Sistemaslunes 26 de marzo de 12
  40. 40. Protocolos ‘ad hoc’ • Pros: – Adaptabilidad: • Modificaciones en código para cada actualización. • Existen protocolos básados en bytes de especificación, categorias ASTERIX de EUROCONTROL – Rendimiento • Contras – Dificultad, desarrollo de analizadores por tecnología. – Tiempo Andrés Pérez y David Gómez 29 Indra y Extrema Sistemaslunes 26 de marzo de 12
  41. 41. Protobuf Mecanismos automáticos de serialización de estructuras de datos. • Alto rendimiento, • sencillez, • adaptabilidad (campos optional), • compatible con las tecnologías planteadas Andrés Pérez y David Gómez 30 Indra y Extrema Sistemaslunes 26 de marzo de 12
  42. 42. ¿Cómo funciona? • Definición de mensajes (estructuras de datos) • Generación de las clases de acceso a las estructuras de datos • Incorporación de las clases generadas al modelo Andrés Pérez y David Gómez 31 Indra y Extrema Sistemaslunes 26 de marzo de 12
  43. 43. ¿Cómo funciona? • Definición de mensajes (estructuras de datos) • Generación de las clases de acceso a las estructuras de datos • Incorporación de las clases generadas al modelo Andrés Pérez y David Gómez 32 Indra y Extrema Sistemaslunes 26 de marzo de 12
  44. 44. Definición de Mensajes • Archivos .proto (pares clave/valor) – clave: identificador del campo del mensaje – valor: de tipo • Números • Booleanos • bytes • mensaje anidado – Marcados como opcionales, obligatorios o repetidos Andrés Pérez y David Gómez 33 Indra y Extrema Sistemaslunes 26 de marzo de 12
  45. 45. Definición de Mensajes • Archivos .proto (pares clave/valor) – clave: identificador del campo del mensaje – valor: de tipo • Números • Booleanos • bytes • mensaje anidado – Marcados como opcionales, obligatorios o repetidos http://code.google.com/intl/es-ES/apis/protocolbuffers/docs/proto.html Andrés Pérez y David Gómez 33 Indra y Extrema Sistemaslunes 26 de marzo de 12
  46. 46. Fichero .proto Andrés Pérez y David Gómez 34 Indra y Extrema Sistemaslunes 26 de marzo de 12
  47. 47. Fichero .proto package  Controllers; option  java_package  =  "com.vts.controller"; message  ControllerMessage  {    enum  CommandType  {        INFO  =  0;        CMD_1  =  1;        CMD_2  =  2;        CMD_3  =  3;         CMD_4  =  4;        CMD_N  =  5;    }    enum  ControllerType  {        UNKNOWN  =  0;        CONTROLLER_1  =  1;        CONTROLLER_2  =  2;       CONTROLLER_3=  3;        CONTROLLER_N  =  4;    }    message  CommandValueDouble{        required  CommandType  commandType  =  1;        required  double  commandValue  =  2;    }    message  CommandValueBool{        required  CommandType  commandType  =  1;        required  bool  commandValue  =  2;    }    message  CommandValueString{        required  CommandType  commandType  =  1;        required  string  commandValue  =  2;    }    message  CommandValueInt32{        required  CommandType  commandType  =  1;        required  int32  commandValue  =  2;    }    required  string  idController  =  2;    required  ControllerType  controllerType  =  3;    repeated  CommandValueDouble  commandValueDouble  =  4;    repeated  CommandValueBool  commandValueBool  =  5;    repeated  CommandValueString  commandValueString  =  6;    repeated  CommandValueInt32  commandValueInt32  =  7; Andrés Pérez y David Gómez 34 Indra y Extrema Sistemaslunes 26 de marzo de 12
  48. 48. Generación de las clases Andrés Pérez y David Gómez 35 Indra y Extrema Sistemaslunes 26 de marzo de 12
  49. 49. Incorporación de clases a modelos • Posibilidades: – almacenamiento: de/a ficheros, BD, ... – comunicación: sockets. • Nuevos campos no rompen la compatibilidad Andrés Pérez y David Gómez 36 Indra y Extrema Sistemaslunes 26 de marzo de 12
  50. 50. Serialización a archivo en C++ Andrés Pérez y David Gómez 37 Indra y Extrema Sistemaslunes 26 de marzo de 12
  51. 51. Serialización a archivo en C++ ControllerMessage  controllerMessage; controllerMessage.set_idController("123456"); controllerMessage.set_controllerType(controllers::ControllerMessage_ControllerType_CONTROLLER_1); controllers::ControllerMessage_CommandValueString*  propiedad  =   controllerMessage.add_CommandValueString(); controllerMessage-­‐>set_commandType(controllers::ControllerMessage_CommandType_CMD_2); controllerMessage-­‐>set_commandValue("VALOR_COMANDO"); fstream  output("fichero.out",  ios::out  |  ios::binary); controllerMessage.SerializeToOstream(&output); Andrés Pérez y David Gómez 37 Indra y Extrema Sistemaslunes 26 de marzo de 12
  52. 52. Envío por Socket C++ Andrés Pérez y David Gómez 38 Indra y Extrema Sistemaslunes 26 de marzo de 12
  53. 53. Envío por Socket C++ ControllerMessage  controllerMessage; controllerMessage.set_commandType(controllers::ControllerMessage_CommandType_CMD_2); int  bufLength  =  controllerMessage.ByteSize(); char*  buffer  =  new  char[bufLength]; google::protobuf::io::ArrayOutputStream  arrayOutput(buffer,  bufLength); google::protobuf::io::CodedOutputStream  codedOutput(&arrayOutput); //Enviamos  primero  el  tamaño  del  mensaje  como  varInt32 codedOutput.WriteVarint32(controllerMessage.ByteSize()); //Y  luego  el  mensaje  en  sí controllerMessage.SerializeToCodedStream(&codedOutput); //codedOutput.ByteCount()  nos  dará  el  tamaño  del  búffer  más   //le  varint  que  indica  el  tamaño  del  mensaje iBufSize  =  codedOutput.ByteCount(); socket-­‐>Send(buffer,  iBufSize); Andrés Pérez y David Gómez 38 Indra y Extrema Sistemaslunes 26 de marzo de 12
  54. 54. .Net Andrés Pérez y David Gómez 39 Indra y Extrema Sistemaslunes 26 de marzo de 12
  55. 55. .Net //Lectura  desde  stream TcpClient  cliente  =  new  TcpClient("192.168.250.50",  12345); ControllerMessage  newController; NetworkStream  stream  =  client.GetStream(); newPerson  =   Serializer.DeserializeWithLengthPrefix<Person>(stream,  PrefixStyle.Fixed32); <TRATAMIENTO  DE  LOS  CAMPOS> //Escritura  hacia  stream ControllerMessage  controller  =  newControllerMessage  Person  (); controller.IdController  =  “132465”; <ASIGNACION  DE  TODOS  LOS  VALORES  DESEADOS> Serializer.Serialize(client,  controller); Andrés Pérez y David Gómez 39 Indra y Extrema Sistemaslunes 26 de marzo de 12
  56. 56. Java Andrés Pérez y David Gómez 40 Indra y Extrema Sistemaslunes 26 de marzo de 12
  57. 57. Java      private  ObjectOutputStream  salida;      private  ObjectInputStream  entrada;      private  ServerSocket  servidor;      private  Socket  conexion;      public  void  readAndWriteMessage()  {        ControllerMessage  controllerMessage  =  null;        servidor  =  new  ServerSocket(  12345,  100  );        conexion  =  servidor.accept();        salida  =  new  ObjectOutputStream(  conexion.getOutputStream()  );              entrada  =  new  ObjectInputStream(  conexion.getInputStream()  );        controllerMessage  =  ControllerMessage.parseDelimitedFrom(entrada);              /*  TRATAMOS  LOS  CAMPOS  OPORTUNOS  */            controllerMessage.writeDelimitedTo(salida);      } Andrés Pérez y David Gómez 40 Indra y Extrema Sistemaslunes 26 de marzo de 12
  58. 58. JMS Comunicación del Servidor a GUI Speaker’s Name 41 Speaker mail – company or communitylunes 26 de marzo de 12
  59. 59. El uso • El servidor envía avisos a los puestos: – Creación de zonas – Alarmas – Actualizaciones de posición de barcos • ¿y si pregunto cada cierto tiempo? (Polling) – La escalabilidad se resiente. Andrés Pérez y David Gómez 42 Indra y Extrema Sistemaslunes 26 de marzo de 12
  60. 60. JMS • JMS es la forma en enviar mensajes en Java Consumer Destination Topic/ Destination Producer Queue Andrés Pérez y David Gómez 43 Indra y Extrema Sistemaslunes 26 de marzo de 12
  61. 61. JMS • JMS es la forma en enviar mensajes en Java Consumer Destination Topic/ Destination Producer Queue Consumer Andrés Pérez y David Gómez 43 Indra y Extrema Sistemaslunes 26 de marzo de 12
  62. 62. JMS • JMS es la forma en enviar mensajes en Java Consumer Destination Topic/ Destination Producer Queue Consumer Topic/ Queue Andrés Pérez y David Gómez 44 Indra y Extrema Sistemaslunes 26 de marzo de 12
  63. 63. JMS • JMS es la forma en enviar mensajes en Java Consumer Destination Topic/ Destination Producer Queue Consumer Consumer Topic/ Queue Andrés Pérez y David Gómez 44 Indra y Extrema Sistemaslunes 26 de marzo de 12
  64. 64. JMS • JMS es la forma en enviar mensajes en Java Consumer Destination Topic/ Destination Producer Queue Consumer Consumer Topic/ Queue Andrés Pérez y David Gómez 44 Indra y Extrema Sistemaslunes 26 de marzo de 12
  65. 65. ¿JMS a pelo? • Demasiado código para enviar un mensaje: • Creación de conexiónes, serialización, gestión deerrores, liberación de recursos Andrés Pérez y David Gómez 45 Indra y Extrema Sistemaslunes 26 de marzo de 12
  66. 66. ¿JMS a pelo? Connection  conn  =  connectionFactory.createConnection(); Session  session  =  conn.createSession(transactional,  ackMode); ObjectMessage  message  =  session.createObjectMessage(myMessageObject); Message  Producer  producer  =  session.createProducer(topicName); producer.send(message); • Demasiado código para enviar un mensaje: • Creación de conexiónes, serialización, gestión deerrores, liberación de recursos Andrés Pérez y David Gómez 45 Indra y Extrema Sistemaslunes 26 de marzo de 12
  67. 67. JMS con Spring JMSTemplate • Se encarga de: – Obtención de la conexión, – Serialización del mensaje – Envío al tópico/Cola – Gestión de errores • Se apoya en – MessageConverter – DestinationResolver Andrés Pérez y David Gómez 46 Indra y Extrema Sistemaslunes 26 de marzo de 12
  68. 68. Dependencias Andrés Pérez y David Gómez 47 Indra y Extrema Sistemaslunes 26 de marzo de 12
  69. 69. Dependencias <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-core</artifactId> <version>5.5.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>3.0.6.RELEASE</version> </dependency> Andrés Pérez y David Gómez 47 Indra y Extrema Sistemaslunes 26 de marzo de 12
  70. 70. Configuracion Andrés Pérez y David Gómez 48 Indra y Extrema Sistemaslunes 26 de marzo de 12
  71. 71. Configuracion <?xml  version="1.0"  encoding="UTF-­‐8"?> <beans>   <bean  name="jmsTemplate"  class="org.springframework.jms.core.JmsTemplate">     <property  name="connectionFactory"  ref="jmsConnectionFactory"  />     <property  name="defaultDestinationName"  value="#{globalTopic.topicName}"/>     <property  name="defaultDestination"  ref="globalTopic"/>     <property  name="receiveTimeout"  value="1"  />     <property  name="pubSubDomain"  value="true"/>     <property  name="messageConverter"  ref="jmsMessageConverter"/>   </bean>   <bean  name="jmsMessageConverter"         class="org.springframework.jms.support.converter.MarshallingMessageConverter">     <property  name="marshaller"  ref="xstreamMarshaller"/>     <property  name="unmarshaller"  ref="xstreamMarshaller"/>   </bean>   <bean  name="jmsEventEmitter"  class="com.vts.jms.JmsEventEmitter"/>   </beans> Andrés Pérez y David Gómez 48 Indra y Extrema Sistemaslunes 26 de marzo de 12
  72. 72. EventEmitter Andrés Pérez y David Gómez 49 Indra y Extrema Sistemaslunes 26 de marzo de 12
  73. 73. EventEmitter public  class  JmsEventEmitter       implements  CameraEventListener,  TrafficEventListener,  ...  {   private  JmsTemplate  jmsTemplate;   private  List<ResponsibilityArea>  areas  =  new  ArrayList<ResponsibilityArea>();   private  void  sendJmsEvent(Locatable  event)  {     if  (event.getGeoPoint()  ==  null)  {       //events  with  no  location  should  be  sent  to  the  defaultDestination       jmsTemplate.convertAndSend(event);     }  else  {       sendToApplicableAreas(event);     }   }   @Override   public  void  onTrafficEvent(TrafficEvent  event)  {     sendJmsEvent(event);   } } Andrés Pérez y David Gómez 49 Indra y Extrema Sistemaslunes 26 de marzo de 12
  74. 74. Para recibir en el cliente Andrés Pérez y David Gómez 50 Indra y Extrema Sistemaslunes 26 de marzo de 12
  75. 75. Para recibir en el cliente <beans>   <bean  id="jmsConnectionFactory"  class="org.apache.activemq.ActiveMQConnectionFactory">     <property  name="brokerURL"   value="tcp://#{systemProperties[jmsHost]?:localhost}:61616"/>   </bean>   <jms:listener-­‐container         connection-­‐factory="jmsConnectionFactory"       destination-­‐type="topic"       message-­‐converter="jmsMessageConverter">     <jms:listener  ref="jmsListener"  method="receiveMessage"   destination="globalTopic"/>     <jms:listener  ref="jmsListener"  method="receiveMessage"         destination="#{systemProperties[responsibilityArea]?:area0}"/>   </jms:listener-­‐container>   <bean  id="jmsListener"  class="com.vts.jms.JmsAreaListener"/> </beans> Andrés Pérez y David Gómez 50 Indra y Extrema Sistemaslunes 26 de marzo de 12
  76. 76. Para recibir en el cliente Andrés Pérez y David Gómez 51 Indra y Extrema Sistemaslunes 26 de marzo de 12
  77. 77. Para recibir en el cliente public  class  JmsAreaListener  {   public  void  receiveMessage(Object  o)  {     if  (o  instanceof  AisTrackPoint)  {       trackPointEventSupport.fire((AisTrackPoint)o);     }  else  if  (o  instanceof  StaticAisMessage)  {       staticAisMessageEventSupport.fire((StaticAisMessage)o);     }     }   }   Andrés Pérez y David Gómez 51 Indra y Extrema Sistemaslunes 26 de marzo de 12
  78. 78. ¡Cuidado con las conexiones! • JMSTemplate abre y cierra nuevas conexiones por cada envío • Solución: PoolConnectionFactory Andrés Pérez y David Gómez 52 Indra y Extrema Sistemaslunes 26 de marzo de 12
  79. 79. ¡Cuidado con las conexiones! • JMSTemplate abre y cierra nuevas conexiones por cada envío • Solución: PoolConnectionFactory <bean  id="jmsConnectionFactory"                        class="org.springframework.jms.connection.CachingConnectionFactory">        <property  name="targetConnectionFactory">                <bean  class="org.apache.activemq.ActiveMQConnectionFactory">                        <property  name="brokerURL"        value="tcp://#{systemProperties[jmsHost]?:localhost}:61616"/>                </bean>        </property> </bean> Andrés Pérez y David Gómez 52 Indra y Extrema Sistemaslunes 26 de marzo de 12
  80. 80. MongoDB Speaker’s Name 53 Speaker mail – company or communitylunes 26 de marzo de 12
  81. 81. ¿Por qué NoSQL? Teorema CAP (Eric Brewer) Source: Nathan Hurst’s Blog Andrés Pérez y David Gómez 54 Indra y Extrema Sistemaslunes 26 de marzo de 12
  82. 82. ¿Por qué NoSQL? Teorema CAP (Eric Brewer) Consistency C Source: Nathan Hurst’s Blog Andrés Pérez y David Gómez 54 Indra y Extrema Sistemaslunes 26 de marzo de 12
  83. 83. ¿Por qué NoSQL? Teorema CAP (Eric Brewer) Consistency Availability C A Source: Nathan Hurst’s Blog Andrés Pérez y David Gómez 54 Indra y Extrema Sistemaslunes 26 de marzo de 12
  84. 84. ¿Por qué NoSQL? Teorema CAP (Eric Brewer) Consistency Availability C A P Partition Tolerance Source: Nathan Hurst’s Blog Andrés Pérez y David Gómez 54 Indra y Extrema Sistemaslunes 26 de marzo de 12
  85. 85. ¿Por qué NoSQL? Teorema CAP (Eric Brewer) Consistency Availability C A P Partition Tolerance Source: Nathan Hurst’s Blog Andrés Pérez y David Gómez 54 Indra y Extrema Sistemaslunes 26 de marzo de 12
  86. 86. ¿Por qué NoSQL? Teorema CAP (Eric Brewer) Consistency Availability C A Sólo 2 P Partition Tolerance Source: Nathan Hurst’s Blog Andrés Pérez y David Gómez 54 Indra y Extrema Sistemaslunes 26 de marzo de 12
  87. 87. ¿Por qué NoSQL? Teorema CAP (Eric Brewer) Consistency Availability A Oracle, MySQL, C Sólo 2 P Partition Tolerance Source: Nathan Hurst’s Blog Andrés Pérez y David Gómez 54 Indra y Extrema Sistemaslunes 26 de marzo de 12
  88. 88. ¿Por qué NoSQL? Teorema CAP (Eric Brewer) Consistency Availability A Oracle, MySQL, C M Hyp is, M on er em Sólo 2 go Ta c Re DB ble ac d , D , H heD at Ba B aS se to re , P Partition Tolerance Source: Nathan Hurst’s Blog Andrés Pérez y David Gómez 54 Indra y Extrema Sistemaslunes 26 de marzo de 12
  89. 89. ¿Por qué NoSQL? Teorema CAP (Eric Brewer) Consistency Availability A Oracle, MySQL, C M Hyp is, M Sólo , on er em uc ra, ort 2 aK go Ta c Co nd m Re Ri DB ble ac B, a de d B, D ass ol , D , H heD hD ple C o,V at Ba B am aS se to yn re D RDBMS , Orientadas a documento P Sim orientadas a columna Key-Value Partition Tolerance Source: Nathan Hurst’s Blog Andrés Pérez y David Gómez 54 Indra y Extrema Sistemaslunes 26 de marzo de 12
  90. 90. Tipos orientadas a Columna orientadas a Documento Key-value orientadas a Grafos Andrés Pérez y David Gómez 55 Indra y Extrema Sistemaslunes 26 de marzo de 12
  91. 91. ¿Por qué MongoDB? • Orientada a Documentos – heterogéneos – Representados en formato JSON (o BSON) • Almacenados en Colecciones (no tablas) • Un poco de SQL: – queries, índices, Referencias externas • Optimizada para escrituras (cc) Photo by Ampersand Duck - http://www.flickr.com/photos/ampersandduck/4941185476 Andrés Pérez y David Gómez 56 Indra y Extrema Sistemaslunes 26 de marzo de 12
  92. 92. Documentos JSON Identificados por un _id Heterogeneos: Identificamos el tipo con _class Andrés Pérez y David Gómez 57 Indra y Extrema Sistemaslunes 26 de marzo de 12
  93. 93. Documentos JSON Identificados por un _id Heterogeneos: Identificamos el tipo con _class { "_id" : "224000999", "_class" : "com.vts.model.Vessel", "flag" : "ALBANIA", "name" : "Sample NOT_AVAILABLE Vessel 224000999", "callsign" : "SV224000999", "toBow" : 25, "toStern" : 5, "toPort" : 5, "toStarboard" : 5, "comments" : "Sample vessel created automatically for test purposes" } Andrés Pérez y David Gómez 57 Indra y Extrema Sistemaslunes 26 de marzo de 12
  94. 94. Consola JS Andrés Pérez y David Gómez 58 Indra y Extrema Sistemaslunes 26 de marzo de 12
  95. 95. Consola JS beleriand:bin dgomez$ ./mongo MongoDB shell version: 1.8.1 connecting to: test > Andrés Pérez y David Gómez 58 Indra y Extrema Sistemaslunes 26 de marzo de 12
  96. 96. Consola JS beleriand:bin dgomez$ ./mongo MongoDB shell version: 1.8.1 connecting to: test > use vts switched to db vts > Andrés Pérez y David Gómez 58 Indra y Extrema Sistemaslunes 26 de marzo de 12
  97. 97. Consola JS beleriand:bin dgomez$ ./mongo MongoDB shell version: 1.8.1 connecting to: test > use vts switched to db vts > show collections > Event WeatherData system.indexes vessel > Andrés Pérez y David Gómez 58 Indra y Extrema Sistemaslunes 26 de marzo de 12
  98. 98. Consola JS beleriand:bin dgomez$ ./mongo MongoDB shell version: 1.8.1 connecting to: test > use vts switched to db vts > show collections > Event WeatherData system.indexes vessel > db.Event.find() > { "_id" : ObjectId("4e0b5b211446446f6be3bb1a"), "_class" : "com.vts.model.events.SystemEvent", "timestamp" : ISODate("2011-06-29T17:04:33.039Z") } { "_id" : ObjectId("4e0b5b3d144676f49946443f"), "_class" : "com.vts.model.events.SystemEvent", "timestamp" : ISODate("2011-06-29T17:05:01.394Z") } > Andrés Pérez y David Gómez 58 Indra y Extrema Sistemaslunes 26 de marzo de 12
  99. 99. SpringData y MongoDB XML namespace para configurar driver Mongo MongoTemplate Conversión de excepciones automática Conversión Configurable JMX monitoring Andrés Pérez y David Gómez 59 Indra y Extrema Sistemaslunes 26 de marzo de 12
  100. 100. Importando Spring Data Andrés Pérez y David Gómez 60 Indra y Extrema Sistemaslunes 26 de marzo de 12
  101. 101. Importando Spring Data <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</ artifactId> <version>2.7.0-rc1</version> </dependency> Andrés Pérez y David Gómez 60 Indra y Extrema Sistemaslunes 26 de marzo de 12
  102. 102. Importando Spring Data <repository> <id>spring-release</id> <name>Spring Maven Release Repository</name> <dependency> <url>http://repo.springsource.org/libs-release</url> </repository> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</ <dependency> artifactId> <version>2.7.0-rc1</version> <groupId>org.springframework.data</groupId> </dependency> <artifactId>spring-data-mongodb</artifactId> <version>1.0.1.RELEASE</version> </dependency> Andrés Pérez y David Gómez 60 Indra y Extrema Sistemaslunes 26 de marzo de 12
  103. 103. Configuración. Spring Namespace Andrés Pérez y David Gómez 61 Indra y Extrema Sistemaslunes 26 de marzo de 12
  104. 104. Configuración. Spring Namespace <?xml  version="1.0"  encoding="UTF-­‐8"?> <beans  xmlns="http://www.springframework.org/schema/beans"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-­‐instance"     xmlns:mongo="http://www.springframework.org/schema/data/mongo"   xmlns:context="http://www.springframework.org/schema/context"   xsi:schemaLocation="http://www.springframework.org/schema/beans                                            http://www.springframework.org/schema/beans/spring-­‐beans.xsd            http://www.springframework.org/schema/data/mongo            http://www.springframework.org/schema/data/mongo/spring-­‐mongo-­‐1.0.xsd                    http://www.springframework.org/schema/context            http://www.springframework.org/schema/context/spring-­‐context.xsd"> </beans> Andrés Pérez y David Gómez 61 Indra y Extrema Sistemaslunes 26 de marzo de 12
  105. 105. Configuración. Spring Namespace <?xml  version="1.0"  encoding="UTF-­‐8"?> <beans  xmlns="http://www.springframework.org/schema/beans"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-­‐instance"     xmlns:mongo="http://www.springframework.org/schema/data/mongo"   xmlns:context="http://www.springframework.org/schema/context"   xsi:schemaLocation="http://www.springframework.org/schema/beans                                            http://www.springframework.org/schema/beans/spring-­‐beans.xsd            http://www.springframework.org/schema/data/mongo            http://www.springframework.org/schema/data/mongo/spring-­‐mongo-­‐1.0.xsd                    http://www.springframework.org/schema/context            http://www.springframework.org/schema/context/spring-­‐context.xsd"> <mongo:db-­‐factory  dbname="vts"/> </beans> Andrés Pérez y David Gómez 61 Indra y Extrema Sistemaslunes 26 de marzo de 12
  106. 106. Configuración. Spring Namespace <?xml  version="1.0"  encoding="UTF-­‐8"?> <beans  xmlns="http://www.springframework.org/schema/beans"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-­‐instance"     xmlns:mongo="http://www.springframework.org/schema/data/mongo"   xmlns:context="http://www.springframework.org/schema/context"   xsi:schemaLocation="http://www.springframework.org/schema/beans                                            http://www.springframework.org/schema/beans/spring-­‐beans.xsd            http://www.springframework.org/schema/data/mongo            http://www.springframework.org/schema/data/mongo/spring-­‐mongo-­‐1.0.xsd                    http://www.springframework.org/schema/context            http://www.springframework.org/schema/context/spring-­‐context.xsd"> <mongo:db-­‐factory  dbname="vts"/>   <bean  id="mongoTemplate"  class="org.springframework.data.mongodb.core.MongoTemplate">     <constructor-­‐arg  name="mongoDbFactory"  ref="mongoDbFactory"  />   </bean> </beans> Andrés Pérez y David Gómez 61 Indra y Extrema Sistemaslunes 26 de marzo de 12
  107. 107. Spring’s MongoTemplate <bean  id="mongoTemplate"  class="org.springframework.data.mongodb.core.MongoTemplate">   <constructor-­‐arg  name="mongoDbFactory"  ref="mongoDbFactory"  /> </bean> Identifica la colección Convierte query a JSON Convierte respuesta (“_class”) Gestiona las conexiones y cursores Convierte las excepciones Andrés Pérez y David Gómez 62 Indra y Extrema Sistemaslunes 26 de marzo de 12
  108. 108. Consultas RDBMS: SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”; 63 Andrés Pérez y David Gómez Indra y Extrema Sistemaslunes 26 de marzo de 12
  109. 109. Consultas RDBMS: SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”; { “flag” : “ALBANIA” } Mongo: 63 Andrés Pérez y David Gómez Indra y Extrema Sistemaslunes 26 de marzo de 12
  110. 110. Consultas RDBMS: SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”; { “flag” : “ALBANIA” } Mongo: Mongo DBCollection vessels = db.getCollection("vessel"); DBObject query = new BasicDBObject(); Driver: query.put("flag", "ALBANIA"); DBCursor albanianShips = vessels.find(query); while (albanianShips.hasNext()) { DBObject result = albanianShips.next(); // Create Vessel object from DBObject } 63 Andrés Pérez y David Gómez Indra y Extrema Sistemaslunes 26 de marzo de 12
  111. 111. Consultas RDBMS: SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”; { “flag” : “ALBANIA” } Mongo: Spring Query query = new Query(Criteria.where("flag").is("ALBANIA"); Mongo List<Vessel> vessels = mongoTemplate.find(query, Vessel.class); Template: 63 Andrés Pérez y David Gómez Indra y Extrema Sistemaslunes 26 de marzo de 12
  112. 112. Consultas RDBMS: SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”; { “flag” : “ALBANIA” } Mongo: Utilizado para Identificación de la colección Serialización JSON Spring Query query = new Query(Criteria.where("flag").is("ALBANIA"); Mongo List<Vessel> vessels = mongoTemplate.find(query, Vessel.class); Template: 63 Andrés Pérez y David Gómez Indra y Extrema Sistemaslunes 26 de marzo de 12
  113. 113. Consultas complejas RDBMS: Andrés Pérez y David Gómez 64 Indra y Extrema Sistemaslunes 26 de marzo de 12
  114. 114. Consultas complejas SELECT * FROM VESSELS WHERE length < 90 AND length > 30 RDBMS: ORDER BY lastUpdate; Mongo: Andrés Pérez y David Gómez 64 Indra y Extrema Sistemaslunes 26 de marzo de 12
  115. 115. Consultas complejas SELECT * FROM VESSELS WHERE length < 90 AND length > 30 RDBMS: ORDER BY lastUpdate; Mongo: { “length” : { $lt : 90, $gt : 30} } Mongo Driver: Andrés Pérez y David Gómez 64 Indra y Extrema Sistemaslunes 26 de marzo de 12
  116. 116. Consultas complejas SELECT * FROM VESSELS WHERE length < 90 AND length > 30 RDBMS: ORDER BY lastUpdate; Mongo: { “length” : { $lt : 90, $gt : 30} } Mongo DBObject query = new BasicDBObject(); DBObject condition = new BasicDBObject("$lt",90); Driver: condition.put("$gt",30); query.put("length", condition); DBObject [] flags = { new BasicDBObject("flag", "ALBANIA"), new BasicDBObject("flag", "SAN MARINO") }; query.put("$or", flags); vessels.find(query); Andrés Pérez y David Gómez 64 Indra y Extrema Sistemaslunes 26 de marzo de 12
  117. 117. Consultas complejas SELECT * FROM VESSELS WHERE length < 90 AND length > 30 RDBMS: ORDER BY lastUpdate; Mongo: { “length” : { $lt : 90, $gt : 30} } Andrés Pérez y David Gómez 64 Indra y Extrema Sistemaslunes 26 de marzo de 12
  118. 118. Consultas complejas SELECT * FROM VESSELS WHERE length < 90 AND length > 30 RDBMS: ORDER BY lastUpdate; Mongo: { “length” : { $lt : 90, $gt : 30} } Criteria criteria = Criteria.where("length"); criteria.gte(from); Spring criteria.lte(to); Mongo Query query = new Query(criteria); query.sort().on("lastUpdate", Order.ASCENDING); Template: List<Vessel> vessels = mongoTemplate.find(query, Vessel.class); Andrés Pérez y David Gómez 64 Indra y Extrema Sistemaslunes 26 de marzo de 12
  119. 119. Inserciones Andrés Pérez y David Gómez 65 Indra y Extrema Sistemaslunes 26 de marzo de 12
  120. 120. Inserciones public class MongoTemplate implements MongoOperations, ApplicationContextAware { public void save(Object objectToSave) public void save(Object objectToSave, String collectionName) } Andrés Pérez y David Gómez 65 Indra y Extrema Sistemaslunes 26 de marzo de 12
  121. 121. AbstractRepository Andrés Pérez y David Gómez 66 Indra y Extrema Sistemaslunes 26 de marzo de 12
  122. 122. AbstractRepository public abstract class AbstractMongoRepository<T> { @Inject protected MongoTemplate mongoTemplate; /** Clase que utiliza Mongo para identificar el nombre de la coleccion */ private Class<T> persistentClass; protected AbstractService(Class<T> persistentClass) { this.persistentClass = persistentClass; } public String determineCollection() { return persistentClass.getSimpleName(); } } Andrés Pérez y David Gómez 66 Indra y Extrema Sistemaslunes 26 de marzo de 12
  123. 123. AbstractRepository (II) Andrés Pérez y David Gómez 67 Indra y Extrema Sistemaslunes 26 de marzo de 12
  124. 124. AbstractRepository (II) public abstract class AbstractMongoRepository<T> { public void save(T e) { mongoTemplate.save(e, determineCollection()); } public void removeById(String id) { Object e = findById(id); if (e != null) { mongoTemplate.remove(e, determineCollection()); } } public T findById(String id) { T t = mongoTemplate.findById(id, persistentClass); if (t == null) { throw new ObjectNotFoundException(persistentClass, id); } return t; } Andrés Pérez y David Gómez } Indra y Extrema Sistemas 67lunes 26 de marzo de 12
  125. 125. VesselRepository Andrés Pérez y David Gómez 68 Indra y Extrema Sistemaslunes 26 de marzo de 12
  126. 126. VesselRepository public class VesselRepository extends AbstractMongoRepository<Vessel> { public VesselRepository() { super(Vessel.class); } } Andrés Pérez y David Gómez 68 Indra y Extrema Sistemaslunes 26 de marzo de 12
  127. 127. A tener en cuenta • Cuidado con los campos transient – La serializacion object <-> JSON se hace por reflexión – Registrar un custom Converter • Queries con multiples valores Andrés Pérez y David Gómez 69 Indra y Extrema Sistemaslunes 26 de marzo de 12
  128. 128. A tener en cuenta • Cuidado con los campos transient – La serializacion object <-> JSON se hace por reflexión – Registrar un custom Converter • Queries con multiples valores Query query = new Query( Criteria .where("length").gte(20) .and("length").lt(60)); Andrés Pérez y David Gómez 69 Indra y Extrema Sistemaslunes 26 de marzo de 12
  129. 129. A tener en cuenta • Cuidado con los campos transient – La serializacion object <-> JSON se hace por reflexión – Registrar un custom Converter • Queries con multiples valores Andrés Pérez y David Gómez 69 Indra y Extrema Sistemaslunes 26 de marzo de 12
  130. 130. A tener en cuenta • Cuidado con los campos transient – La serializacion object <-> JSON se hace por reflexión – Registrar un custom Converter • Queries con multiples valores Query query = new Query( Criteria .where("length").gte(20).lte(60)); Andrés Pérez y David Gómez 69 Indra y Extrema Sistemaslunes 26 de marzo de 12
  131. 131. Q&A Speaker’s Name 70 Speaker mail – company or communitylunes 26 de marzo de 12

×