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.
1. Integrando Sistemas reales con
REST, JMS, Protobuf y MongoDB
Andrés Perez
Indra
David Gómez
Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
5. El caso real.
Control de tráfico marítimo
Andrés Pérez y David Gómez 4
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
9. El Problema:
La escalabilidad
Andrés Pérez y David Gómez 7
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
12. El problema:
la escablabilidad
Andrés Pérez y David Gómez 10
Indra y Extrema Sistemas
lunes 26 de marzo de 12
13. La arquitectura
Speaker’s Name 11
Speaker mail – company or community
lunes 26 de marzo de 12
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 community
lunes 26 de marzo de 12
15. REST
Comunicación síncrona entre GUI y Servidor
Speaker’s Name 13
Speaker mail – company or community
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
18. Comparación
Andrés Pérez y David Gómez 16
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
21. (Spring) REST en el servidor
Andrés Pérez y David Gómez 17
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
24. Un Controlador de Zona (I)
Andrés Pérez y David Gómez 19
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
26. Un Controlador de Zona (II)
Andrés Pérez y David Gómez 20
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
28. Un Controlador de Zona (III)
Andrés Pérez y David Gómez 21
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
30. Configuración
Andrés Pérez y David Gómez 22
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
32. RestTemplate
• Invocar servicios REST desde los GUI
Andrés Pérez y David Gómez 23
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
34. RestTemplate
• RestTemplate implements RestOperations
Andrés Pérez y David Gómez 24
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
36. Protobuf
Comunicación entre dispositivos y servidor/GUI
.Net/C++/Java
Speaker’s Name 25
Speaker mail – company or community
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
46. Fichero .proto
Andrés Pérez y David Gómez 34
Indra y Extrema Sistemas
lunes 26 de marzo de 12
48. Generación de las clases
Andrés Pérez y David Gómez 35
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
50. Serialización a archivo en
C++
Andrés Pérez y David Gómez 37
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
52. Envío por Socket
C++
Andrés Pérez y David Gómez 38
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
54. .Net
Andrés Pérez y David Gómez 39
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
56. Java
Andrés Pérez y David Gómez 40
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
58. JMS
Comunicación del Servidor a GUI
Speaker’s Name 41
Speaker mail – company or community
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
68. Dependencias
Andrés Pérez y David Gómez 47
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
70. Configuracion
Andrés Pérez y David Gómez 48
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
72. EventEmitter
Andrés Pérez y David Gómez 49
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
74. Para recibir en el cliente
Andrés Pérez y David Gómez 50
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
76. Para recibir en el cliente
Andrés Pérez y David Gómez 51
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
80. MongoDB
Speaker’s Name 53
Speaker mail – company or community
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
94. Consola JS
Andrés Pérez y David Gómez 58
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
100. Importando Spring Data
Andrés Pérez y David Gómez 60
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
103. Configuración.
Spring Namespace
Andrés Pérez y David Gómez 61
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
108. Consultas
RDBMS: SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;
63
Andrés Pérez y David Gómez
Indra y Extrema Sistemas
lunes 26 de marzo de 12
109. Consultas
RDBMS: SELECT * FROM VESSEL WHERE FLAG = “ALBANIA”;
{ “flag” : “ALBANIA” }
Mongo:
63
Andrés Pérez y David Gómez
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
113. Consultas complejas
RDBMS:
Andrés Pérez y David Gómez 64
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
119. Inserciones
Andrés Pérez y David Gómez 65
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
121. AbstractRepository
Andrés Pérez y David Gómez 66
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
123. AbstractRepository (II)
Andrés Pérez y David Gómez 67
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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
67
lunes 26 de marzo de 12
125. VesselRepository
Andrés Pérez y David Gómez 68
Indra y Extrema Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
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 Sistemas
lunes 26 de marzo de 12
131. Q&A
Speaker’s Name 70
Speaker mail – company or community
lunes 26 de marzo de 12