Date post: | 10-May-2015 |
Category: |
Technology |
Upload: | david-gomez-garcia |
View: | 1,336 times |
Download: | 1 times |
Andrés Perez IndraDavid Gómez Extrema Sistemas
Integrando Sistemas reales conREST, JMS, Protobuf y MongoDB
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
2
David GómezSw Architect & Trainer
@dgomezg
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
2
Andrés PérezSw Architect
David GómezSw Architect & Trainer
@dgomezg
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
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
3
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
El caso real.Control de tráfico marítimo
4
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
El caso real.Control de tráfico marítimo
5
Emisor AIX
3-5 min
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
El caso real.Control de tráfico marítimo
6
Emisor AIX
3-5 min
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
El caso real.Control de tráfico marítimo
6
Emisor AIX
3-5 min
Receptor GPS
Goniometro
Estación Meteo,
Cámaras,
...
Radar (3 s)
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
El Problema: La escalabilidad
7
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
El Problema: La escalabilidad
8
Por cada barco:
Recepción y procesamiento de señales (nº)
Transacciones,
Cálculo de alarmas
Gestión de Históricos
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
El Problema: La escalabilidad
9
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)
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
El problema: la escablabilidad
10
lunes 26 de marzo de 12
Speaker’s NameSpeaker mail – company or community
La arquitectura
11
lunes 26 de marzo de 12
Speaker’s NameSpeaker mail – company or community
12
ServerRadar
Cameras
Gonio
GUI 1
GUI 2
DB
Protobuf
Spring Data
JMSJMS
REST
REST
lunes 26 de marzo de 12
Speaker’s NameSpeaker mail – company or community
RESTComunicación síncrona entre GUI y Servidor
13
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
14
¿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
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿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
15
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Comparación
16
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Comparación
16
GET http://server:port/zones/POST http://server:port/zones/388GET http://server:port/zones/388PUT http://server:port/zones/388
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Comparación
16
GET http://server:port/zones/POST http://server:port/zones/388GET http://server:port/zones/388PUT http://server:port/zones/388
http://server:port/listZoneshttp://server:port/createNewZone http://server:port/getZone?id=388http://server:port/updateZone?id=388
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
(Spring) REST en el servidor
17
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
(Spring) REST en el servidor
17
<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>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿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
18
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Un Controlador de Zona (I)
19
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Un Controlador de Zona (I)
19
@Controllerpublic 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()));
}}
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Un Controlador de Zona (II)
20
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Un Controlador de Zona (II)
20
@Controllerpublic 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(); }}
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Un Controlador de Zona (III)
21
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Un Controlador de Zona (III)
21
@Controllerpublic 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); }
}
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Configuración
22
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Configuración
22
<?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>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
23
RestTemplate
• Invocar servicios REST desde los GUI
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
23
RestTemplate
• Invocar servicios REST desde los GUI@Componentpublic 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); }}
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
24
RestTemplate
• RestTemplate implements RestOperations
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
24
RestTemplate
• RestTemplate implements RestOperationspublic 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;
...}
lunes 26 de marzo de 12
Speaker’s NameSpeaker mail – company or community
ProtobufComunicación entre dispositivos y servidor/GUI
.Net/C++/Java
25
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
26
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
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿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
27
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿REST?
REST, XML (Servidor java <-> Cliente java)• Pros:
– Sencillez. Ampliamente extendido– Compatible con las tecnologías propuestas– Adaptabilidad
• Contras:– rendimiento insuficiente para dispositivos
28
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
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
29
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Protobuf
Mecanismos automáticos de serialización de estructuras de datos.
• Alto rendimiento,• sencillez,• adaptabilidad (campos optional),
• compatible con las tecnologías planteadas
30
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿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
31
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿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
32
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
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
33
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
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
33
http://code.google.com/intl/es-ES/apis/protocolbuffers/docs/proto.html
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Fichero .proto
34
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Fichero .proto
34
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;
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Generación de las clases
35
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Incorporación de clases a modelos
36
• Posibilidades: – almacenamiento: de/a ficheros, BD, ...– comunicación: sockets.
• Nuevos campos no rompen la compatibilidad
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Serialización a archivo en C++
37
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Serialización a archivo en C++
37
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);
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Envío por SocketC++
38
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Envío por SocketC++
38
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 varInt32codedOutput.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 mensajeiBufSize = codedOutput.ByteCount();socket-‐>Send(buffer, iBufSize);
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
.Net
39
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
.Net
39
//Lectura desde streamTcpClient 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 streamControllerMessage controller = newControllerMessage Person ();controller.IdController = “132465”;<ASIGNACION DE TODOS LOS VALORES DESEADOS>Serializer.Serialize(client, controller);
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Java
40
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Java
40
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); }
lunes 26 de marzo de 12
Speaker’s NameSpeaker mail – company or community
JMSComunicación del Servidor a GUI
41
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
42
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.
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
JMS
• JMS es la forma en enviar mensajes en Java
43
Topic/Queue
ProducerConsumer
Destination Destination
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
JMS
• JMS es la forma en enviar mensajes en Java
43
Topic/Queue
ProducerConsumer
Destination Destination
Consumer
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
JMS
• JMS es la forma en enviar mensajes en Java
44
Topic/Queue
ProducerConsumer
Destination Destination
Consumer
Topic/Queue
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
JMS
• JMS es la forma en enviar mensajes en Java
44
Topic/Queue
ProducerConsumer
Destination Destination
Consumer
Topic/Queue
Consumer
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
JMS
• JMS es la forma en enviar mensajes en Java
44
Topic/Queue
ProducerConsumer
Destination Destination
Consumer
Topic/Queue
Consumer
Producer
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿JMS a pelo?
45
• Demasiado código para enviar un mensaje:• Creación de conexiónes, serialización, gestión deerrores, liberación de
recursos
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿JMS a pelo?
45
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
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
JMS con SpringJMSTemplate
• 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
46
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Dependencias
47
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Dependencias
47
<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>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Configuracion
48
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Configuracion
48
<?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>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
EventEmitter
49
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
EventEmitter
49
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); }
}
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Para recibir en el cliente
50
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Para recibir en el cliente
50
<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>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Para recibir en el cliente
51
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Para recibir en el cliente
51
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); } } }
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¡Cuidado con las conexiones!
• JMSTemplate abre y cierra nuevas conexiones por cada envío
• Solución: PoolConnectionFactory
52
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¡Cuidado con las conexiones!
• JMSTemplate abre y cierra nuevas conexiones por cada envío
• Solución: PoolConnectionFactory
52
<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>
lunes 26 de marzo de 12
Speaker’s NameSpeaker mail – company or community
MongoDB
53
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿Por qué NoSQL?
54
Teorema CAP (Eric Brewer)
Source: Nathan Hurst’s Blog
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿Por qué NoSQL?
54
Teorema CAP (Eric Brewer)
CConsistency
Source: Nathan Hurst’s Blog
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿Por qué NoSQL?
54
Teorema CAP (Eric Brewer)
C AConsistency Availability
Source: Nathan Hurst’s Blog
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿Por qué NoSQL?
54
Teorema CAP (Eric Brewer)
C A
P
Consistency Availability
Partition ToleranceSource: Nathan Hurst’s Blog
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿Por qué NoSQL?
54
Teorema CAP (Eric Brewer)
C A
P
Consistency Availability
Partition ToleranceSource: Nathan Hurst’s Blog
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿Por qué NoSQL?
54
Teorema CAP (Eric Brewer)
C A
P
Consistency Availability
Partition Tolerance
Sólo 2
Source: Nathan Hurst’s Blog
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿Por qué NoSQL?
54
Teorema CAP (Eric Brewer)
C A
P
Consistency Availability
Partition Tolerance
Sólo 2
Oracle, MySQL,
Source: Nathan Hurst’s Blog
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿Por qué NoSQL?
54
Teorema CAP (Eric Brewer)
C A
P
Consistency Availability
Partition Tolerance
Sólo 2
Oracle, MySQL,
MongoDB, DataStore,
HyperTable, HBase
Redis, Mem
cacheDB
Source: Nathan Hurst’s Blog
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿Por qué NoSQL?
54
Teorema CAP (Eric Brewer)
C A
P
Consistency Availability
Partition Tolerance
Sólo 2
Oracle, MySQL,
MongoDB, DataStore,
HyperTable, HBase
Redis, Mem
cacheDBDyn
amo, V
oldem
ort,
Cas
sand
ra,
Simple
DB, Cou
chDB,
RiaK
RDBMSOrientadas a documento
orientadas a columnaKey-Value
Source: Nathan Hurst’s Blog
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Tipos
55
orientadas a Documento
orientadas a GrafosKey-value
orientadas a Columna
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
¿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
56
(cc) Photo by Ampersand Duck - http://www.flickr.com/photos/ampersandduck/4941185476
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Documentos JSON
57
Identificados por un _idHeterogeneos: Identificamos el tipo con _class
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Documentos JSON
57
{ "_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"}
Identificados por un _idHeterogeneos: Identificamos el tipo con _class
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consola JS
58
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consola JS
58
beleriand:bin dgomez$ ./mongoMongoDB shell version: 1.8.1connecting to: test>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consola JS
58
beleriand:bin dgomez$ ./mongoMongoDB shell version: 1.8.1connecting to: test> > use vtsswitched to db vts>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consola JS
58
beleriand:bin dgomez$ ./mongoMongoDB shell version: 1.8.1connecting to: test> > use vtsswitched to db vts>> show collectionsEventWeatherDatasystem.indexesvessel>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consola JS
58
beleriand:bin dgomez$ ./mongoMongoDB shell version: 1.8.1connecting to: test> > use vtsswitched to db vts>> show collectionsEventWeatherDatasystem.indexesvessel>> 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") }>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
SpringData y MongoDB
XML namespace para configurar driver Mongo
MongoTemplate
Conversión de excepciones automática
Conversión Configurable
JMX monitoring
59
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Importando Spring Data
60
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Importando Spring Data
60
<dependency><groupId>org.mongodb</groupId><artifactId>mongo-java-driver</artifactId><version>2.7.0-rc1</version>
</dependency>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Importando Spring Data
60
<dependency><groupId>org.mongodb</groupId><artifactId>mongo-java-driver</artifactId><version>2.7.0-rc1</version>
</dependency>
<repository> <id>spring-release</id> <name>Spring Maven Release Repository</name> <url>http://repo.springsource.org/libs-release</url></repository>
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.0.1.RELEASE</version></dependency>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Configuración. Spring Namespace
61
lunes 26 de marzo de 12
<?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ómezIndra y Extrema Sistemas
Configuración. Spring Namespace
61
lunes 26 de marzo de 12
<?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ómezIndra y Extrema Sistemas
Configuración. Spring Namespace
61
<mongo:db-‐factory dbname="vts"/>
lunes 26 de marzo de 12
<?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ómezIndra y Extrema Sistemas
Configuración. Spring Namespace
61
<mongo:db-‐factory dbname="vts"/>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-‐arg name="mongoDbFactory" ref="mongoDbFactory" /> </bean>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Spring’s MongoTemplate
62
Identifica la colección
Convierte query a JSON
Convierte respuesta (“_class”)
Gestiona las conexiones y cursores
Convierte las excepciones
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-‐arg name="mongoDbFactory" ref="mongoDbFactory" /></bean>
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consultas
63
SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”; RDBMS:
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consultas
63
SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;
{ “flag” : “ALBANIA” }
RDBMS:
Mongo:
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consultas
63
SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;
{ “flag” : “ALBANIA” }
DBCollection vessels = db.getCollection("vessel");
DBObject query = new BasicDBObject();query.put("flag", "ALBANIA"); DBCursor albanianShips = vessels.find(query);while (albanianShips.hasNext()) { DBObject result = albanianShips.next(); // Create Vessel object from DBObject}
RDBMS:
Mongo:
Mongo
Driver:
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consultas
63
SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;
{ “flag” : “ALBANIA” }
Query query = new Query(Criteria.where("flag").is("ALBANIA");
List<Vessel> vessels = mongoTemplate.find(query, Vessel.class);
RDBMS:
Mongo:
Spring
Mongo
Template:
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consultas
63
SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;
{ “flag” : “ALBANIA” }
Query query = new Query(Criteria.where("flag").is("ALBANIA");
List<Vessel> vessels = mongoTemplate.find(query, Vessel.class);
Utilizado para
Identificación de la colección
Serialización JSON
RDBMS:
Mongo:
Spring
Mongo
Template:
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consultas complejas
64
RDBMS:
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consultas complejas
64
SELECT * FROM VESSELS WHERE length < 90 AND length > 30ORDER BY lastUpdate;RDBMS:
Mongo:
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consultas complejas
64
SELECT * FROM VESSELS WHERE length < 90 AND length > 30ORDER BY lastUpdate;
{ “length” : { $lt : 90, $gt : 30}}
RDBMS:
Mongo:
Mongo
Driver:
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consultas complejas
64
SELECT * FROM VESSELS WHERE length < 90 AND length > 30ORDER BY lastUpdate;
{ “length” : { $lt : 90, $gt : 30}}
DBObject query = new BasicDBObject();DBObject condition = new BasicDBObject("$lt",90);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);
RDBMS:
Mongo:
Mongo
Driver:
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consultas complejas
64
SELECT * FROM VESSELS WHERE length < 90 AND length > 30ORDER BY lastUpdate;
{ “length” : { $lt : 90, $gt : 30}}
RDBMS:
Mongo:
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Consultas complejas
64
SELECT * FROM VESSELS WHERE length < 90 AND length > 30ORDER BY lastUpdate;
{ “length” : { $lt : 90, $gt : 30}}
Criteria criteria = Criteria.where("length");criteria.gte(from);criteria.lte(to);
Query query = new Query(criteria);query.sort().on("lastUpdate", Order.ASCENDING);
List<Vessel> vessels = mongoTemplate.find(query, Vessel.class);
RDBMS:
Mongo:
Spring
Mongo
Template:
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Inserciones
65
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
Inserciones
65
public class MongoTemplate implements MongoOperations, ApplicationContextAware {
public void save(Object objectToSave)
public void save(Object objectToSave, String collectionName)
}
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
AbstractRepository
66
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
AbstractRepository
66
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(); }}
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
AbstractRepository (II)
67
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
AbstractRepository (II)
67
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; }}
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
VesselRepository
68
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
VesselRepository
68
public class VesselRepository extends AbstractMongoRepository<Vessel> {
public VesselRepository() { super(Vessel.class); }
}
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
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
69
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
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
69
Query query = new Query( Criteria .where("length").gte(20) .and("length").lt(60));
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
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
69
lunes 26 de marzo de 12
Andrés Pérez y David GómezIndra y Extrema Sistemas
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
69
Query query = new Query( Criteria .where("length").gte(20).lte(60));
lunes 26 de marzo de 12
Speaker’s NameSpeaker mail – company or community
Q&A
70
lunes 26 de marzo de 12