Desarrollo Grails  en Español  Enrique Medina Montenegro         @emedinam                              1
Índice1. Acerca del ponente2. Observatorio de Grails3. cuestamenos.com4. Ruegos y preguntas5. Contacto                    ...
1. Acerca del ponente•Ingeniero en Informática (Univ. Alicante - 1991/1996)•Fundador del•Socio fundador/desarrollador de•C...
Índice1. Acerca del ponente2. Observatorio de Grails3. cuestamenos.com4. Ruegos y preguntas5. Contacto                    ...
2. Observatorio de Grails ✓¿Cómo surge la idea?   ‣Asistencia al Spring 2GX Day (18/Feb/2010)   ‣Falta de recursos en espa...
2. Observatorio de Grails ✓ Estructura del Observatorio  ‣ Actualidad (noticias, blogs, liberaciones, etc)        Inserció...
2. Observatorio de Grails ✓ Estructura del Observatorio  ‣ Artículos (cosecha propia y colaboraciones)                  Ex...
2. Observatorio de Grails ✓ Estructura del Observatorio  ‣ Tutoriales (recopilaciones y manuales)                Más detal...
2. Observatorio de Grails ✓ Estructura del Observatorio  ‣ Eventos (congresos, conferencias, seminarios, cursos)          ...
2. Observatorio de Grails ✓ Estructura del Observatorio  ‣ Otras ayudas            Tu puesto de mandos para tecnología Gra...
2. Observatorio de Grails ✓ Métricas del Observatorio   ‣ Más de 1.000 entradas en Actualidad   ‣ Más de 150 entradas en A...
2. Observatorio de Grails‣ Estadísticas de uso (vista global)                                       12
2. Observatorio de Grails‣ Gráfico de visitas por ubicación                                     13
2. Observatorio de Grails‣ Gráfico de visitas por ubicación                                     13
2. Observatorio de Grails‣ Gráfico de visitas por ubicación                                     13
2. Observatorio de Grails‣ Visitantes nuevos y recurrentes                                    14
2. Observatorio de Grails‣ Fidelización de visitas                            15
2. Observatorio de Grails‣ Foro de Grails en castellano                                 16
2. Observatorio de Grails‣ Equipo humano                            17
2. Observatorio de Grails ✓ Hoja de ruta   ‣ Continuar la labor de divulgación y promoción de Grails   ‣ Nuevas ideas de p...
Índice1. Acerca del ponente2. Observatorio de Grails3. cuestamenos.com4. Ruegos y preguntas5. Contacto                    ...
3. cuestamenos.com✓ La idea...  ‣ Viajes y más viajes: ¿puedo ahorrar reservando vuelos/coches/hoteles?  ‣ Cashback: ¿hay ...
3. cuestamenos.com✓ El equipo...  ‣ Tres desarrolladores (cada uno de su padre y de su madre):    ★ 1 PHPero, algo de Java...
3. cuestamenos.com✓ El proyecto...  ‣ Estructura Front-office / Back-office:    ★ Aplicación única, no modularizable    ★ ...
3. cuestamenos.com✓ El proyecto (en imágenes)...                                 23
3. cuestamenos.com✓ Reto 1. Pero, ¿dónde está mi  conexión? ‣ Requisito inicial:    ★ Utilizar DBCP como pool de      cone...
3. cuestamenos.com✓ Reto 1. Pero, ¿dónde está mi  conexión?                                      grails-app/conf/BootStrap...
3. cuestamenos.com✓ Reto 1. Pero, ¿dónde está mi        grails-app/conf/DataSource.groovy  conexión? ‣ Requisito inicial: ...
3. cuestamenos.com✓ Reto 2. MailService y su  dependencia del ‘request’ ‣ Requisito inicial:    ★ Gestión de notificacione...
3. cuestamenos.com✓ Reto 2. MailService y su  dependencia del ‘request’                                       grails-app/c...
3. cuestamenos.com✓ Reto 3. Demasiados correos ‣ Requisito inicial:    ★ Enviar correo por cada acción      del usuario: r...
3. cuestamenos.com✓ Reto 3. Demasiados correos           CorreoAsincronoService.groovy ‣ Requisito inicial:    ★ Enviar co...
3. cuestamenos.com✓ Reto 4. Aprovéchate de la  configuración de Grails ‣ Requisito inicial:    ★ Parametrizar múltiples   ...
3. cuestamenos.com                                  grails-app/conf/Config.groovy✓ Reto 4. Aprovéchate de la  configuració...
3. cuestamenos.com                                  grails-app/conf/Config.groovy✓ Reto 4. Aprovéchate de la  configuració...
3. cuestamenos.com✓ Reto 5. Autenticarse con el  correo en vez del usuario ‣ Requisito inicial:    ★ Utilizar el nombre de...
EmailAuthenticationProvider.groovy   3. cuestamenos.com✓ Reto 5. Autenticarse con el  correo en vez del usuario ‣ Requisit...
EmailAuthenticationProvider.groovy     3. cuestamenos.com✓ Reto 5. Autenticarse con el  correo en vez del usuario ‣ Requis...
EmailAuthenticationProvider.groovy     3. cuestamenos.com✓ Reto 5. Autenticarse con el  correo en vez del usuario ‣ Requis...
3. cuestamenos.com✓ Reto 6. ¿Qué ha pasado? ‣ Requisito inicial:    ★ Poder dar soporte ante      problemas al usuario ‣ P...
3. cuestamenos.com                                     grails-app/conf/spring/resources.groovy✓ Reto 6. ¿Qué ha pasado? ‣ ...
3. cuestamenos.com                                     grails-app/conf/spring/resources.groovy✓ Reto 6. ¿Qué ha pasado? ‣ ...
3. cuestamenos.com✓ Reto 7. URLs ‘bonitas’ y  ‘marcables’ como favoritas ‣ Requisito inicial:    ★ No queremos ver URLs in...
3. cuestamenos.com                  grails-app/conf/URLMappings.groovy✓ Reto 7. URLs ‘bonitas’ y  ‘marcables’ como favorit...
3. cuestamenos.com✓ Reto 8. Darle nombre a los  tipos con enumerados ‣ Requisito inicial:    ★ Necesitamos definir todo ti...
3. cuestamenos.com                                          TipoEstadoAuditoria.groovy✓ Reto 8. Darle nombre a los  tipos ...
3. cuestamenos.com                                          TipoEstadoAuditoria.groovy✓ Reto 8. Darle nombre a los  tipos ...
3. cuestamenos.com✓ Reto 9. Mapea, mapea ‣ Requisito inicial:    ★ Mapear las clases del dominio y      sus asociaciones ‣...
3. cuestamenos.com                                        Historico.groovy✓ Reto 9. Mapea, mapea ‣ Requisito inicial:    ★...
3. cuestamenos.com                                        Historico.groovy✓ Reto 9. Mapea, mapea ‣ Requisito inicial:    ★...
3. cuestamenos.com✓ Reto 10. Sé DRY, mi amigo ‣ Requisito inicial:    ★ Consultar los programas      disponibles ordenados...
3. cuestamenos.com                  Historico.groovy✓ Reto 10. Sé DRY, mi amigo ‣ Requisito inicial:    ★ Consultar los pr...
3. cuestamenos.com✓ Reto 11. Disculpe, pero la  transaccionalidad es mía ‣ Requisito inicial:    ★ Ejecutar acciones de se...
3. cuestamenos.com✓ Reto 11. Disculpe, pero la             GestionService.groovy  transaccionalidad es mía ‣ Requisito ini...
3. cuestamenos.com✓ Reto 12. ¿Por qué no habláis de la misma forma? ‣ Requisito inicial:   ★ Integrarse de forma automátic...
3. cuestamenos.com✓ Reto 12. ¿Por qué no habláis de la misma forma? ‣ Requisito inicial:   ★ Integrarse de forma automátic...
3. cuestamenos.com✓ Reto 12. ¿Por qué no habláis de la misma forma? ‣ Requisito inicial:   ★ Integrarse de forma automátic...
3. cuestamenos.com✓ Reto 12. ¿Por qué no habláis de la misma forma? ‣ Requisito inicial:   ★ Integrarse de forma automátic...
3. cuestamenos.com✓ Otros retos ‣ Socializar la aplicación:   ★ Integración con API de Facebook   ★ MSN, GMail, Paypal ‣ A...
3. cuestamenos.com✓ elasticsearch. ‣ Ya sabes, para Buscar:   ★ Open Source (Apache 2)   ★ Motor distribuido, RESTful, sob...
3. cuestamenos.com✓ Integración en la aplicación ‣ Mediante plugin:   ★ Todavía muy virgen; no soporta mucha funcionalidad...
3. cuestamenos.com✓ Integración en la aplicación (...continua)  ‣ Analizador propio de español                            ...
3. cuestamenos.com✓ Integración en la aplicación (...continua)  ‣ Analizador propio de español                SpanishAnaly...
3. cuestamenos.com✓ Integración en la aplicación (...continua)  ‣ Analizador propio de español                SpanishAnaly...
3. cuestamenos.com✓ Integración en la aplicación (...continua)  ‣ Creación del índice y mapeo del tipo ‘producto’         ...
3. cuestamenos.com✓ Integración en la aplicación (...continua)  ‣ Creación del índice y mapeo del tipo ‘producto’     $ cu...
3. cuestamenos.com✓ Integración en la aplicación (...continua)  ‣ Creación del índice y mapeo del tipo ‘producto’  $ curl ...
3. cuestamenos.com✓ Integración en la aplicación (...continua)  ‣ Configuración del cliente                               ...
3. cuestamenos.com✓ Integración en la aplicación (...continua)  ‣ Configuración del cliente     grails-app/conf/spring/res...
3. cuestamenos.com✓ Integración en la aplicación (...continua)  ‣ Configuración del cliente     grails-app/conf/spring/res...
3. cuestamenos.com✓ Integración en la aplicación (...continua)  ‣ Indexación por lotes (bulk indexing)                    ...
3. cuestamenos.com✓ Integración en la aplicación (...continua)  ‣ Indexación por lotes (bulk indexing)       IndexRequestQ...
3. cuestamenos.com✓ Integración en la aplicación (...continua)  ‣ Búsqueda avanzada                                       ...
3. cuestamenos.com    ✓ Integración en la aplicación (...continua)         ‣ Búsqueda avanzada{    "from" : 0, size: 10,  ...
3. cuestamenos.com    ✓ Integración en la aplicación (...continua)         ‣ Búsqueda avanzada{    "from" : 0, size: 10,  ...
3. cuestamenos.com    ✓ Integración en la aplicación (...continua)         ‣ Búsqueda avanzada{    "from" : 0, size: 10,  ...
3. cuestamenos.com    ✓ Integración en la aplicación (...continua)         ‣ Búsqueda avanzada{    "from" : 0, size: 10,  ...
3. cuestamenos.com    ✓ Integración en la aplicación (...continua)         ‣ Búsqueda avanzada{    "from" : 0, size: 10,  ...
3. cuestamenos.com✓ Métricas del proyecto...    ‣ Equipo: 3 personas a tiempo parcial    ‣ Tiempo de desarrollo inicial: 6...
3. cuestamenos.com✓ Lecciones aprendidas...  ‣ Aproximación inicial a la búsqueda:    ★ Uso ‘gratuito’ del plugin Searchab...
3. cuestamenos.com✓ Hoja de ruta...  ‣ Nueva interfaz completamente rediseñada    ★ Más usable, más intuitiva, más sencill...
Índice1. Acerca del ponente2. Observatorio de Grails3. cuestamenos.com4. Ruegos y preguntas5. Contacto                    ...
5. Contacto              E-mail: emedina@cuestamenos.com              Twitter: @emedinam                       @observadeg...
Upcoming SlideShare
Loading in...5
×

Desarrollo Grails en Español (Spring I/O - 2011)

3,174

Published on

Presentación en el evento de Spring I/O de 2011 sobre el Observatorio de Grails y el desarrollo de la web cuestamenos.com

Published in: Technology
0 Comments
7 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,174
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
0
Comments
0
Likes
7
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Tuvimos que tunear el async mail por el tema del MailSender vs JavaMailSender para MIME y algunos problemas con plantillas y el uso del CC y BCC\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Comentar tb que otra ventaja de los enums es que pueden asociarse al messages.properties y proporcionar traducción automática\n
  • Comentar tb que otra ventaja de los enums es que pueden asociarse al messages.properties y proporcionar traducción automática\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Imaginemos que construimos una aplicación y queremos proporciona búsqueda sobre la misma, y entonces nos damos cuenta de que buscar es complicado. Pero lo que queremos es que nuestro motor de búsqueda sea rápido, sencillo de configurar y completamente libre de esquema. También queremos indexar la información de forma simple con JSON sobre HTTP, queremos que nuestro motor de búsqueda esté siempre disponible, queremos empezar con una máquina y luego escalar a cientos de ellas, queremos búsqueda en tiempo real, y queremos una solución que funcione en la nube.\n\nLos índices se descomponen en shards, donde cada shard puede tener 0 o más réplicas. Cada nodo en el cluster aloja uno o más shards, y actúa como un coordinador que delega operaciones a los shards correctos. El balanceo y el enrutado se gestionan de forma automática y entre bambalinas.\n\nEl estado del cluster (incluyendo el log de transacciones) puede ser regenerado a partir de cada nodo local (por defecto), o a partir de un repositorio compartido (como NFS o Amazon S3). Cuando se utiliza un repositorio compartido, el estado se replica de forma asíncrona.\nIncluso si se utiliza un repositorio compartido, el índice podría mantenerse completamente en memoria y al mismo tiempo hacer una recuperación completa si se produce un apagado del cluster.\n\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript of "Desarrollo Grails en Español (Spring I/O - 2011)"

    1. 1. Desarrollo Grails en Español Enrique Medina Montenegro @emedinam 1
    2. 2. Índice1. Acerca del ponente2. Observatorio de Grails3. cuestamenos.com4. Ruegos y preguntas5. Contacto 2
    3. 3. 1. Acerca del ponente•Ingeniero en Informática (Univ. Alicante - 1991/1996)•Fundador del•Socio fundador/desarrollador de•Colaborador de la comunidad “Open Source”•Más de 3 años usando Groovy/Grails•Blogger, liberal, padre, emprendedor 3
    4. 4. Índice1. Acerca del ponente2. Observatorio de Grails3. cuestamenos.com4. Ruegos y preguntas5. Contacto 4
    5. 5. 2. Observatorio de Grails ✓¿Cómo surge la idea? ‣Asistencia al Spring 2GX Day (18/Feb/2010) ‣Falta de recursos en español ‣Aumento de interés por Grails en comunidad hispana ‣Centralizar información y estructurarla ✓¿Cómo se desarrolla la idea? ‣Equipo de 3 personas heterogéneas ‣Uso de Wordpress (sí, has oido bien, PHP) ‣Multitud de plugins WP (Twitter, Scoring, etc.) ‣Dedicación, esfuerzo e hipoteca de tiempo libre 5
    6. 6. 2. Observatorio de Grails ✓ Estructura del Observatorio ‣ Actualidad (noticias, blogs, liberaciones, etc) Inserción manual diaria (excepto fines de semana) 6
    7. 7. 2. Observatorio de Grails ✓ Estructura del Observatorio ‣ Artículos (cosecha propia y colaboraciones) Experiencias propias de desarrollo 7
    8. 8. 2. Observatorio de Grails ✓ Estructura del Observatorio ‣ Tutoriales (recopilaciones y manuales) Más detalle, más calidad, paso a paso 8
    9. 9. 2. Observatorio de Grails ✓ Estructura del Observatorio ‣ Eventos (congresos, conferencias, seminarios, cursos) No te pierdas nada que ocurra cerca de ti 9
    10. 10. 2. Observatorio de Grails ✓ Estructura del Observatorio ‣ Otras ayudas Tu puesto de mandos para tecnología Grails 10
    11. 11. 2. Observatorio de Grails ✓ Métricas del Observatorio ‣ Más de 1.000 entradas en Actualidad ‣ Más de 150 entradas en Artículos/Tutoriales/Eventos ‣ Más de 150 comentarios de usuarios 11
    12. 12. 2. Observatorio de Grails‣ Estadísticas de uso (vista global) 12
    13. 13. 2. Observatorio de Grails‣ Gráfico de visitas por ubicación 13
    14. 14. 2. Observatorio de Grails‣ Gráfico de visitas por ubicación 13
    15. 15. 2. Observatorio de Grails‣ Gráfico de visitas por ubicación 13
    16. 16. 2. Observatorio de Grails‣ Visitantes nuevos y recurrentes 14
    17. 17. 2. Observatorio de Grails‣ Fidelización de visitas 15
    18. 18. 2. Observatorio de Grails‣ Foro de Grails en castellano 16
    19. 19. 2. Observatorio de Grails‣ Equipo humano 17
    20. 20. 2. Observatorio de Grails ✓ Hoja de ruta ‣ Continuar la labor de divulgación y promoción de Grails ‣ Nuevas ideas de producción propia: ★ ¿Sabías que...? ★ Entre bastidores ★ Podcasts ‣ Colaboraciones de usuarios ‣ Expansión a otros idiomas ‣ Comunidad/Grupo de Usuarios (Meetups) ¡¡¡Te estamos esperando!!! 18
    21. 21. Índice1. Acerca del ponente2. Observatorio de Grails3. cuestamenos.com4. Ruegos y preguntas5. Contacto 19
    22. 22. 3. cuestamenos.com✓ La idea... ‣ Viajes y más viajes: ¿puedo ahorrar reservando vuelos/coches/hoteles? ‣ Cashback: ¿hay algo de ésto aquí en España? ‣ Espíritu emprendedor: sin financiación (coste 0) ‣ Retos técnicos: ★ Tecnología a usar: seguro que no es JSF ★ APIs heterogéneas (REST, SOAP, HTTP, Offline) ★ Integración OAuth con Facebook, MSN, GMail ★ URLs ‘amigables’ ★ Front-office vs Back-office ★ Motor de búsqueda de tiendas/productos/promociones 20
    23. 23. 3. cuestamenos.com✓ El equipo... ‣ Tres desarrolladores (cada uno de su padre y de su madre): ★ 1 PHPero, algo de Java (disp. móviles), algo de .NET ★ 1 Javero, nada de Groovy, nada de Grails ★ 1 Javero, experiencia en Groovy, algo de Grails ‣ Curva de aprendizaje: factor clave de desarrollo ‣ Entorno de desarrollo (herramientas gratuitas): ★ IDE STS (SpringSource) ★ Unfuddle: SVN ★ Comunicación Skype 21
    24. 24. 3. cuestamenos.com✓ El proyecto... ‣ Estructura Front-office / Back-office: ★ Aplicación única, no modularizable ★ Front-office: interfaz web cliente con jQuery y GSP ★ Back-office: plataforma Grails + plugins + librerías de terceros ‣ Parte pública / parte privada (administración) ‣ Uso de todos los artefactos disponibles en Grails (+ plugins): ★ Controladores, dominio, servicios, taglibs, pruebas ★ Seguridad por roles: usuario/administrador ★ GORM, scaffolding, i18n, deployment 22
    25. 25. 3. cuestamenos.com✓ El proyecto (en imágenes)... 23
    26. 26. 3. cuestamenos.com✓ Reto 1. Pero, ¿dónde está mi conexión? ‣ Requisito inicial: ★ Utilizar DBCP como pool de conexiones (OOTB) ‣ Problema surgido: ★ Conexiones perdidas con MySQL cada día ‣ Solución aplicada: ★ Tomcat, tú te encargas (JNDI) 24
    27. 27. 3. cuestamenos.com✓ Reto 1. Pero, ¿dónde está mi conexión? grails-app/conf/BootStrap.groovy ‣ Requisito inicial: ★ Utilizar DBCP como pool de conexiones (OOTB) ‣ Problema surgido: ★ Conexiones perdidas con MySQL cada día ‣ Solución aplicada: ★ Tomcat, tú te encargas (JNDI) 24
    28. 28. 3. cuestamenos.com✓ Reto 1. Pero, ¿dónde está mi grails-app/conf/DataSource.groovy conexión? ‣ Requisito inicial: ★ Utilizar DBCP como pool de conexiones (OOTB) ‣ Problema surgido: ★ Conexiones perdidas con MySQL cada día ‣ Solución aplicada: ★ Tomcat, tú te encargas (JNDI) 24
    29. 29. 3. cuestamenos.com✓ Reto 2. MailService y su dependencia del ‘request’ ‣ Requisito inicial: ★ Gestión de notificaciones de comisiones y boletines de noticias a usuarios ‣ Problema surgido: ★ Error al renderizar plantillas GSP en procesos asíncronos ‣ Solución aplicada: ★ Simular el ‘request’ mediante una dependencia 25
    30. 30. 3. cuestamenos.com✓ Reto 2. MailService y su dependencia del ‘request’ grails-app/conf/BuildConfig.groovy ‣ Requisito inicial: ★ Gestión de notificaciones de comisiones y boletines de noticias a usuarios ‣ Problema surgido: ★ Error al renderizar plantillas GSP en procesos asíncronos ‣ Solución aplicada: ★ Simular el ‘request’ mediante una dependencia 25
    31. 31. 3. cuestamenos.com✓ Reto 3. Demasiados correos ‣ Requisito inicial: ★ Enviar correo por cada acción del usuario: registro, integración FB, contacto, etc. ‣ Problema surgido: ★ Proceso síncrono. Cola de mensajes inmanejable ‣ Solución aplicada: ★ Uso del plugin AsynchronousMail (tuneado) 26
    32. 32. 3. cuestamenos.com✓ Reto 3. Demasiados correos CorreoAsincronoService.groovy ‣ Requisito inicial: ★ Enviar correo por cada acción del usuario: registro, integración FB, contacto, etc. ‣ Problema surgido: ★ Proceso síncrono. Cola de mensajes inmanejable ‣ Solución aplicada: ★ Uso del plugin AsynchronousMail (tuneado) 26
    33. 33. 3. cuestamenos.com✓ Reto 4. Aprovéchate de la configuración de Grails ‣ Requisito inicial: ★ Parametrizar múltiples aspectos de la aplicación ‣ Problema surgido: ★ Parémetros dispersos ‣ Solución aplicada: ★ Uso de Config.groovy 27
    34. 34. 3. cuestamenos.com grails-app/conf/Config.groovy✓ Reto 4. Aprovéchate de la configuración de Grails ‣ Requisito inicial: ★ Parametrizar múltiples aspectos de la aplicación ‣ Problema surgido: ★ Parémetros dispersos ‣ Solución aplicada: ★ Uso de Config.groovy 27
    35. 35. 3. cuestamenos.com grails-app/conf/Config.groovy✓ Reto 4. Aprovéchate de la configuración de Grails ‣ Requisito inicial: ★ Parametrizar múltiples aspectos de la aplicación ‣ Problema surgido: ★ Parémetros dispersos ‣ Solución aplicada: ★ Uso de Config.groovy 27
    36. 36. 3. cuestamenos.com✓ Reto 5. Autenticarse con el correo en vez del usuario ‣ Requisito inicial: ★ Utilizar el nombre de usuario para autenticarse en la web ‣ Problema surgido: ★ La gente olvida su usuario, pero nunca su correo email ‣ Solución aplicada: ★ Creación de un proveedor de autenticación basado en email 28
    37. 37. EmailAuthenticationProvider.groovy 3. cuestamenos.com✓ Reto 5. Autenticarse con el correo en vez del usuario ‣ Requisito inicial: ★ Utilizar el nombre de usuario para autenticarse en la web ‣ Problema surgido: ★ La gente olvida su usuario, pero nunca su correo email ‣ Solución aplicada: ★ Creación de un proveedor de autenticación basado en email 28
    38. 38. EmailAuthenticationProvider.groovy 3. cuestamenos.com✓ Reto 5. Autenticarse con el correo en vez del usuario ‣ Requisito inicial: ★ Utilizar el nombre de usuario para autenticarse en la web ‣ Problema surgido: ★ La gente olvida su usuario, pero nunca su correo email grails-app/conf/spring/resources.groovy ‣ Solución aplicada: ★ Creación de un proveedor de autenticación basado en email 28
    39. 39. EmailAuthenticationProvider.groovy 3. cuestamenos.com✓ Reto 5. Autenticarse con el correo en vez del usuario ‣ Requisito inicial: ★ Utilizar el nombre de usuario para autenticarse en la web ‣ Problema surgido: ★ La gente olvida su usuario, pero nunca su correo email grails-app/conf/spring/resources.groovy ‣ Solución aplicada: ★ Creación de un proveedor de autenticación basado en email grails-app/conf/SecurityConfig.groovy 28
    40. 40. 3. cuestamenos.com✓ Reto 6. ¿Qué ha pasado? ‣ Requisito inicial: ★ Poder dar soporte ante problemas al usuario ‣ Problema surgido: ★ No podíamos auditar todo el código en todas las clases ‣ Solución aplicada: ★ Capturar excepciones de forma centralizada y auditar 29
    41. 41. 3. cuestamenos.com grails-app/conf/spring/resources.groovy✓ Reto 6. ¿Qué ha pasado? ‣ Requisito inicial: ★ Poder dar soporte ante problemas al usuario ‣ Problema surgido: ★ No podíamos auditar todo el código en todas las clases ‣ Solución aplicada: ★ Capturar excepciones de forma centralizada y auditar 29
    42. 42. 3. cuestamenos.com grails-app/conf/spring/resources.groovy✓ Reto 6. ¿Qué ha pasado? ‣ Requisito inicial: ★ Poder dar soporte ante problemas al usuario ‣ Problema surgido: ExceptionResolver.groovy ★ No podíamos auditar todo el código en todas las clases ‣ Solución aplicada: ★ Capturar excepciones de forma centralizada y auditar 29
    43. 43. 3. cuestamenos.com✓ Reto 7. URLs ‘bonitas’ y ‘marcables’ como favoritas ‣ Requisito inicial: ★ No queremos ver URLs infinitas que no sean legibles ‣ Problema surgido: ★ Hacer una reescritura manual puede ser tedioso ‣ Solución aplicada: ★ Exprimir el URLMappings.groovy 30
    44. 44. 3. cuestamenos.com grails-app/conf/URLMappings.groovy✓ Reto 7. URLs ‘bonitas’ y ‘marcables’ como favoritas ‣ Requisito inicial: ★ No queremos ver URLs infinitas que no sean legibles ‣ Problema surgido: ★ Hacer una reescritura manual puede ser tedioso ‣ Solución aplicada: ★ Exprimir el URLMappings.groovy 30
    45. 45. 3. cuestamenos.com✓ Reto 8. Darle nombre a los tipos con enumerados ‣ Requisito inicial: ★ Necesitamos definir todo tipo de conceptos: afiliados, auditorías, estados, prioridades, etc ‣ Problema surgido: ★ Declarar los tipos como variables finales estáticas es demasiado engorroso ‣ Solución aplicada: ★ Aprovecharse de los ‘enums’ 31
    46. 46. 3. cuestamenos.com TipoEstadoAuditoria.groovy✓ Reto 8. Darle nombre a los tipos con enumerados ‣ Requisito inicial: ★ Necesitamos definir todo tipo de conceptos: afiliados, auditorías, estados, prioridades, etc ‣ Problema surgido: ★ Declarar los tipos como variables finales estáticas es demasiado engorroso ‣ Solución aplicada: ★ Aprovecharse de los ‘enums’ 31
    47. 47. 3. cuestamenos.com TipoEstadoAuditoria.groovy✓ Reto 8. Darle nombre a los tipos con enumerados ‣ Requisito inicial: ★ Necesitamos definir todo tipo de conceptos: afiliados, auditorías, estados, prioridades, etc ‣ Problema surgido: TipoMetodoPago.groovy ★ Declarar los tipos como variables finales estáticas es demasiado engorroso ‣ Solución aplicada: ★ Aprovecharse de los ‘enums’ 31
    48. 48. 3. cuestamenos.com✓ Reto 9. Mapea, mapea ‣ Requisito inicial: ★ Mapear las clases del dominio y sus asociaciones ‣ Problema surgido: ★ Demasiadas sentencias SQL y problemas de rendimiento ‣ Solución aplicada: ★ Tunear y optimizar los mapeos hasta el más mínimo detalle 32
    49. 49. 3. cuestamenos.com Historico.groovy✓ Reto 9. Mapea, mapea ‣ Requisito inicial: ★ Mapear las clases del dominio y sus asociaciones ‣ Problema surgido: ★ Demasiadas sentencias SQL y problemas de rendimiento ‣ Solución aplicada: ★ Tunear y optimizar los mapeos hasta el más mínimo detalle 32
    50. 50. 3. cuestamenos.com Historico.groovy✓ Reto 9. Mapea, mapea ‣ Requisito inicial: ★ Mapear las clases del dominio y sus asociaciones ‣ Problema surgido: ★ Demasiadas sentencias SQL y problemas de rendimiento Usuario.groovy ‣ Solución aplicada: ★ Tunear y optimizar los mapeos hasta el más mínimo detalle 32
    51. 51. 3. cuestamenos.com✓ Reto 10. Sé DRY, mi amigo ‣ Requisito inicial: ★ Consultar los programas disponibles ordenados por todo tipo de criterios ‣ Problema surgido: ★ Componer un HQL cada vez que se necesitan ‣ Solución aplicada: ★ Definir ‘named queries’ 33
    52. 52. 3. cuestamenos.com Historico.groovy✓ Reto 10. Sé DRY, mi amigo ‣ Requisito inicial: ★ Consultar los programas disponibles ordenados por todo tipo de criterios ‣ Problema surgido: ★ Componer un HQL cada vez que se necesitan ‣ Solución aplicada: ★ Definir ‘named queries’ 33
    53. 53. 3. cuestamenos.com✓ Reto 11. Disculpe, pero la transaccionalidad es mía ‣ Requisito inicial: ★ Ejecutar acciones de servicio en una transacción atómica ‣ Problema surgido: ★ Por defecto, todos los métodos de un servicio son transacc. ‣ Solución aplicada: ★ Utilizar @Transactional sólo en los métodos que aplica 34
    54. 54. 3. cuestamenos.com✓ Reto 11. Disculpe, pero la GestionService.groovy transaccionalidad es mía ‣ Requisito inicial: ★ Ejecutar acciones de servicio en una transacción atómica ‣ Problema surgido: ★ Por defecto, todos los métodos de un servicio son transacc. ‣ Solución aplicada: ★ Utilizar @Transactional sólo en los métodos que aplica 34
    55. 55. 3. cuestamenos.com✓ Reto 12. ¿Por qué no habláis de la misma forma? ‣ Requisito inicial: ★ Integrarse de forma automática con las afiliados y sus tiendas ‣ Problema surgido: ★ Cada afiliado ofrece una API de acceso distinto: REST, SOAP, HTTP ‣ Solución aplicada: ★ Usar tecnologías existentes mediante plugin o librerías: HTTPBuilder 35
    56. 56. 3. cuestamenos.com✓ Reto 12. ¿Por qué no habláis de la misma forma? ‣ Requisito inicial: ★ Integrarse de forma automática con las afiliados y sus tiendas ‣ Problema surgido: ★ Cada afiliado ofrece una API de acceso distinto: REST, SOAP, HTTP ‣ Solución aplicada: ★ Usar tecnologías existentes mediante plugin o librerías: HTTPBuilder Llamada HTTP 35
    57. 57. 3. cuestamenos.com✓ Reto 12. ¿Por qué no habláis de la misma forma? ‣ Requisito inicial: ★ Integrarse de forma automática con las afiliados y sus tiendas ‣ Problema surgido: ★ Cada afiliado ofrece una API de acceso distinto: REST, SOAP, HTTP ‣ Solución aplicada: ★ Usar tecnologías existentes mediante plugin o librerías: HTTPBuilder Llamada REST 35
    58. 58. 3. cuestamenos.com✓ Reto 12. ¿Por qué no habláis de la misma forma? ‣ Requisito inicial: ★ Integrarse de forma automática con las afiliados y sus tiendas ‣ Problema surgido: ★ Cada afiliado ofrece una API de acceso distinto: REST, SOAP, HTTP ‣ Solución aplicada: ★ Usar tecnologías existentes mediante plugin o librerías: HTTPBuilder Llamada SOAP 35
    59. 59. 3. cuestamenos.com✓ Otros retos ‣ Socializar la aplicación: ★ Integración con API de Facebook ★ MSN, GMail, Paypal ‣ Automatización de procesos: ★ Trabajos Quartz para comprobación de programas, comisiones, pagos, inactividad de cuentas, suscripciones VIP, etc. ‣ Procesos ‘al fondo’: ★ Uso del plugin BackgroundThread ‣ Búsqueda avanzada de programas/productos/promociones: ★ Comenzamos con el plugin Searchable: requiere almacenar los productos en BBDD; resultó ser un cuello de botella enorme ★ Pero además necesitábamos: búsquedas ‘multifacet’, indexador en servidor (distinta JVM), búsqueda avanzada (fuzzy, AND/OR, etc.) ★ Y se hizo la luz: ElasticSearch... 36
    60. 60. 3. cuestamenos.com✓ elasticsearch. ‣ Ya sabes, para Buscar: ★ Open Source (Apache 2) ★ Motor distribuido, RESTful, sobre Lucene ‣ Libre de esquema & Orientado a Documento: ★ Modelo NoSQL basado en JSON ‣ Búsqueda: ★ DSL basado en JSON: queries, facets, highlighting, scripting, percolator, geobúsquedas, etc. ★ Multi tenancy: búsqueda por múltiples índices ‣ Distribuido: ★ Índices --> fragmentos (shards) --> réplicas ★ Cluster --> nodos --> 1..n fragmentos ★ Balanceo, enrutado, tolerancia a fallos (Gateway), etc. 37
    61. 61. 3. cuestamenos.com✓ Integración en la aplicación ‣ Mediante plugin: ★ Todavía muy virgen; no soporta mucha funcionalidad ‣ Mediante la API de ES: ★ REST API --> Expuesta mediante HTTP, thrift, memcached ★ Java API --> Asíncrona, soporta 100% la REST API ★ Groovy API --> Asíncrona, envoltorio limitado sobre la Java API ‣ Clientes: ★ Node --> Se une al cluster como un nodo más y puede almacenar información o no, incluso configurarse como cluster local. ★ Transport --> No se une al cluster; conexión remota http://www.elasticsearch.org/guide/reference/java-api/client.html 38
    62. 62. 3. cuestamenos.com✓ Integración en la aplicación (...continua) ‣ Analizador propio de español 39
    63. 63. 3. cuestamenos.com✓ Integración en la aplicación (...continua) ‣ Analizador propio de español SpanishAnalyzer.java 39
    64. 64. 3. cuestamenos.com✓ Integración en la aplicación (...continua) ‣ Analizador propio de español SpanishAnalyzer.java elasticsearch/config/elasticsearch.yml 39
    65. 65. 3. cuestamenos.com✓ Integración en la aplicación (...continua) ‣ Creación del índice y mapeo del tipo ‘producto’ 40
    66. 66. 3. cuestamenos.com✓ Integración en la aplicación (...continua) ‣ Creación del índice y mapeo del tipo ‘producto’ $ curl -XPUT http://localhost:9200/cuestamenos/ -d {     settings : {         index : {             number_of_shards : 3,             number_of_replicas : 2         }     } } 40
    67. 67. 3. cuestamenos.com✓ Integración en la aplicación (...continua) ‣ Creación del índice y mapeo del tipo ‘producto’ $ curl -XPUT http://localhost:9200/cuestamenos/producto/mapping -d 40
    68. 68. 3. cuestamenos.com✓ Integración en la aplicación (...continua) ‣ Configuración del cliente 41
    69. 69. 3. cuestamenos.com✓ Integración en la aplicación (...continua) ‣ Configuración del cliente grails-app/conf/spring/resources.groovy 41
    70. 70. 3. cuestamenos.com✓ Integración en la aplicación (...continua) ‣ Configuración del cliente grails-app/conf/spring/resources.groovy TransportClientFactoryBean.groovy 41
    71. 71. 3. cuestamenos.com✓ Integración en la aplicación (...continua) ‣ Indexación por lotes (bulk indexing) 42
    72. 72. 3. cuestamenos.com✓ Integración en la aplicación (...continua) ‣ Indexación por lotes (bulk indexing) IndexRequestQueue.groovy 42
    73. 73. 3. cuestamenos.com✓ Integración en la aplicación (...continua) ‣ Búsqueda avanzada 43
    74. 74. 3. cuestamenos.com ✓ Integración en la aplicación (...continua) ‣ Búsqueda avanzada{ "from" : 0, size: 10, "sort" : [ { "_score" : "desc" } ], “query” : { "filtered" : { "query" : { "bool" : { "must" : { "field" : { "_all" : "horror" } }, "must" : { "field" : { “_all" : "noche" } } } }, "filter" : { "bool" : { "must" : { "term" : { "categorias1" : "Ocio y cultura" } }, "must" : { "term" : { "tienda" : "Casa del Libro" } } } } } }, "facets" : { "categorias2" : { "terms" : { "field" : "categorias2", "size" : 10 }, "facet_filter" : { "term" : { "categorias1" : "Ocio y cultura" } } }, "tienda" : { "terms" : { "field" : "tienda", "size" : 10 }, "facet_filter" : { "term" : { "tienda" : "Casa del Libro" } } } }} 43
    75. 75. 3. cuestamenos.com ✓ Integración en la aplicación (...continua) ‣ Búsqueda avanzada{ "from" : 0, size: 10, "sort" : [ { "_score" : "desc" } ], “query” : { "filtered" : { "query" : { "bool" : { ElasticSearchUtil.groovy "must" : { "field" : { "_all" : "horror" } }, "must" : { "field" : { “_all" : "noche" } } } }, "filter" : { "bool" : { "must" : { "term" : { "categorias1" : "Ocio y cultura" } }, "must" : { "term" : { "tienda" : "Casa del Libro" } } } } } }, "facets" : { "categorias2" : { "terms" : { "field" : "categorias2", "size" : 10 }, "facet_filter" : { "term" : { "categorias1" : "Ocio y cultura" } } }, "tienda" : { "terms" : { "field" : "tienda", "size" : 10 }, "facet_filter" : { "term" : { "tienda" : "Casa del Libro" } } } }} 43
    76. 76. 3. cuestamenos.com ✓ Integración en la aplicación (...continua) ‣ Búsqueda avanzada{ "from" : 0, size: 10, "sort" : [ { "_score" : "desc" } ], “query” : { "filtered" : { "query" : { "bool" : { ElasticSearchUtil.groovy "must" : { "field" : { "_all" : "horror" } }, "must" : { "field" : { “_all" : "noche" } } } }, "filter" : { "bool" : { "must" : { "term" : { "categorias1" : "Ocio y cultura" } }, "must" : { "term" : { "tienda" : "Casa del Libro" } } } } } }, "facets" : { "categorias2" : { "terms" : { "field" : "categorias2", "size" : 10 }, "facet_filter" : { "term" : { "categorias1" : "Ocio y cultura" } } }, "tienda" : { "terms" : { "field" : "tienda", "size" : 10 }, "facet_filter" : { "term" : { "tienda" : "Casa del Libro" } } } }} 43
    77. 77. 3. cuestamenos.com ✓ Integración en la aplicación (...continua) ‣ Búsqueda avanzada{ "from" : 0, size: 10, "sort" : [ { "_score" : "desc" } ], “query” : { "filtered" : { "query" : { "bool" : { ElasticSearchUtil.groovy "must" : { "field" : { "_all" : "horror" } }, "must" : { "field" : { “_all" : "noche" } } } }, "filter" : { "bool" : { "must" : { "term" : { "categorias1" : "Ocio y cultura" } }, "must" : { "term" : { "tienda" : "Casa del Libro" } } } } } }, "facets" : { "categorias2" : { "terms" : { "field" : "categorias2", "size" : 10 }, "facet_filter" : { "term" : { "categorias1" : "Ocio y cultura" } } }, "tienda" : { "terms" : { "field" : "tienda", "size" : 10 }, "facet_filter" : { "term" : { "tienda" : "Casa del Libro" } } } }} 43
    78. 78. 3. cuestamenos.com ✓ Integración en la aplicación (...continua) ‣ Búsqueda avanzada{ "from" : 0, size: 10, "sort" : [ { "_score" : "desc" } ], ElasticSearchUtil.groovy “query” : { "filtered" : { "query" : { "bool" : { "must" : { "field" : { "_all" : "horror" } }, "must" : { "field" : { “_all" : "noche" } } } }, "filter" : { "bool" : { "must" : { "term" : { "categorias1" : "Ocio y cultura" } }, "must" : { "term" : { "tienda" : "Casa del Libro" } } } } } }, "facets" : { "categorias2" : { "terms" : { "field" : "categorias2", "size" : 10 }, "facet_filter" : { "term" : { "categorias1" : "Ocio y cultura" } } }, "tienda" : { "terms" : { "field" : "tienda", "size" : 10 }, "facet_filter" : { "term" : { "tienda" : "Casa del Libro" } } } }} 43
    79. 79. 3. cuestamenos.com✓ Métricas del proyecto... ‣ Equipo: 3 personas a tiempo parcial ‣ Tiempo de desarrollo inicial: 6 meses 44
    80. 80. 3. cuestamenos.com✓ Lecciones aprendidas... ‣ Aproximación inicial a la búsqueda: ★ Uso ‘gratuito’ del plugin Searchable ★ No prever funcionalidad futura ‣ Gestión automática de comisiones: ★ Esfuerzo gigante inicial; actualmente se paga solo ‣ Uso ‘indiscriminado’ de plugins: ★ A veces no hay que matar moscas a cañonazos ‣ Sin comunidad, no hay nada que hacer ‣ Seguiremos usando Grails para futuros proyectos (ya en marcha) 45
    81. 81. 3. cuestamenos.com✓ Hoja de ruta... ‣ Nueva interfaz completamente rediseñada ★ Más usable, más intuitiva, más sencilla ‣ Gestión avanzada de referidos (apadrinados) ‣ Búsquedas de cupones/promociones ‣ Cliente iPhone con tecnologías HTML5+CSS3 (Phonegap) ‣ Actualización a Grails 2.0 (OSGi) cuando esté disponible 46
    82. 82. Índice1. Acerca del ponente2. Observatorio de Grails3. cuestamenos.com4. Ruegos y preguntas5. Contacto 47
    83. 83. 5. Contacto E-mail: emedina@cuestamenos.com Twitter: @emedinam @observadegrails @cuestamenos http://observatoriodegrails.com http://forodegrails.com http://cuestamenos.com GRACIAS POR VUESTRA ATENCIÓN 48

    ×