Software Guru Conference & Expo 2014

Enviando alarmas desde aplicaciones con jAlarms

Alguna vez han tenido que implementar un mecanismo para notificar al administrador de un sistema cuando algo deja de funcionar en una aplicación, porque dicha aplicación está corriendo en un servidor dentro de un datacenter y tal vez haya un problema durante un fin de semana y hay que corregirlo cuanto antes, pero no pueden estar monitoreando dicha aplicación las 24 horas?

Bueno pues yo sí he tenido que hacer algo así, por eso es que decidí reimplementarlo como una librería con licencia LGPL y subirla a SourceForge. Se llama jAlarms y la idea es que simplemente deben crear y configurar el componente AlarmSender en su aplicación y entonces pueden usarlo para mandar una alarma desde cualquier lugar en su aplicaci&aocute;n. Se puede configurar fácilmente con Spring, pero no es forzoso (aunque algunos componentes tienen la anotación de @Required para validarse en Spring).

La librería ya incluye dos canales para enviar alarmas: Mail (por medio de JavaMailSender de Spring) y MSN (utilizando esta librería para MSN desde Java). Espero pronto poder implementar un canal para JavaMail sin Spring (para la gente que no pueda o no quiera meter Spring a su aplicación y solamente necesite enviar notificaciones por correo), así como un canal para enviar alarmas por SMPP (el protocolo que se usa con servidores de mensajes de las compañías celulares).

Es relativamente sencillo implementar sus propios canales si así lo requieren (por ejemplo para GoogleTalk o iChat o algun web service para envio de SMS con otro proveedor, etc); pueden implementar la interfaz AlarmChannel o mejor aún solamente extender la clase abstracta AbstractAlarmChannel, en cuyo caso ya solamente tienen que hacer en su clase lo necesario para conectarse al proveedor del servicio de notificaciones y devolver un Runnable en el método createSendTask, el cual debe enviar el mensaje dentro de su implementación de run(). Esto es porque el canal abstracto ya implementa una cola con un thread pool para enviar los mensajes de manera diferida, de modo que el envio de varias alarmas no detiene el funcionamiento normal de la aplicación, además de implementar un mecanismo en conjunto con el AlarmSender para evitar el envio de varios mensajes iguales seguidos.

La página del proyecto actualmente no ofrece demasiada info porque apenas subi la primera versión; pero ya tiene ligas a documentación y un ejemplo sencillo. Ya pueden bajar el primer release de ahi mismo, o pueden obtener el código fuente directo del repositorio de Subversion, ahi encontrarán un script de ANT para que compilen el código y tengan el JAR para que lo usen en sus aplicaciones.

Actualización: Anexo los slides de la presentación de jAlarms realizada durante el SpringIO 2010.

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de benek

De entrada se ve muy

De entrada se ve muy útil!

No me imagino aún como detectas los errores o si eso hay que implementarlo, pero el hecho de que ya gestione los errores y los pueda enviar por diferentes canales suena interesante!

En cada posible error se debe hacer una llamada a AlarmSender? O es un thread que corre en background que configuras para q actúe cuando detecte el error?

De todos modos ya estoy bajando el código :P

Javier Benek
http://twitter.com/xbenek

Imagen de ezamudio

La detección...

La detección corre por tu cuenta. La idea es que por ejemplo en algun try-catch donde luego ya no sabes ni qué hacer porque fue un error muy grave, puedas enviar una alarma, simplemente invocando AlarmSender.send() y listo. O cuando detectas alguna cosa que es mejor que revise un humano.

Lo que implementa el AlarmSender, además de los canales por mail y MSN, es que si tu envio de alarma corre por ejemplo dentro de un ciclo y estás enviando el mismo mensaje varias veces, no tienes que preocuparte de que vayas a llenar el buzón de los destinatarios o atascar el MSN del sysadmin con mensajes repetidos; el framework se da cuenta cuando estás enviando el mismo mensaje varias veces y solamente lo envía cada cierto tiempo (es configurable). Y sí hay un thread separado para el envio de las alarmas, de modo que no se afecta el flujo de tu programa porque el SMTP está lento por ejemplo.

Imagen de iberck

El poder de las alarmas

El poder de una librería no está en su tamaño si no en su utilidad y este es un claro ejemplo para sistemas críticos.
Gracias por la librería, estoy seguro que a más de uno nos dirá lo que está pasando antes que cualquier usuario ;)
Saludos

https://nbtapestrysupport.dev.java.net/

Verdadera Necesidad

Hola a todos.
Es grandiosa la libreria que mencionas, ya permite revisar el funcionamiento de la aplicación, sobre todo porque las aplicaciones utilizan una de las leyes de morphy (jejejeje)
" la probabilidad de que algo falle cuando no debe es del 100%".
Gran aporte para la comunidad JavaMéxico.
Saludos

Imagen de rugi

Felicitaciones..

Hombre Enrique!
Felicitaciones por tu librería y gracias por poner disponible el código... mira que muchos esperabamos tener la oportunidad de ver código tuyo y ahora, eres tú mismo el que nos lo comparte ;)

Saludos!!
RuGI

Imagen de ezamudio

j8583 también

El j8583 ya tiene más tiempo en SF ese también lo pueden ver, es un poco más elaborado que jAlarms, que la verdad es muy sencillo pero muy útil.

Imagen de benek

Twitter

Así es, el j8583 aún no lo he publicado en el twitter de @javamexico pero en un rato más lo haré ;-)

Saludos!

Imagen de ezamudio

TwitterChannel

Pues ya que está tan de moda Twitter, la verdad que me puse a pensar y le encontré una utilidad, más allá de estar chismeando de lo que hacen los demás.

Me imaginé un sysadmin (bueno de hecho lo conozco en la vida real) que tiene que monitorear varias aplicaciones Java corriendo en varios servers. Si cada aplicación tiene una cuenta en Twitter y la usa para publicar ahí su status (sobre todo anomalías, no sirve de nada que diga "estoy bien" a menos que quieras tener un uptime o algo así cada X tiempo), entonces el sysadmin puede tener una lista (o una cuenta especial para esto) en Twitter donde sigue las cuentas de las aplicaciones; si usa un cliente de escritorio de los que avisan cuando alguien actualiza su status, entonces se facilita bastante el trabajo de monitoreo.

Es por esto que hice el TwitterChannel, un nuevo canal para enviar alarmas con jAlarms. Hay que hacer varias cosas por fuera de la aplicación pero es solamente para configurar; básicamente todo lo que acabo de decir arriba.

Por ejemplo si tengo una aplicación que quiero monitorear usando Twitter, entonces creo una cuenta para mi app (supongamos que le ponemos jalarmstest). Para que no haya broncas de privacidad, la configuro para que los tweets sean privados y haya que aprobar a los seguidores. Luego con mi propia cuenta de Twitter (y/o la del sysadmin y/o la de los de soporte, etc) sigo esa cuenta que acabo de hacer. Con eso ya tengo preparado el usuario que va a postear status y los usuarios que lo van a monitorear.

Lo que sigue es correr el programita TwitterAuth que viene en la librería (todavía no hago otro release, ahorita solamente por SVN bajando el código y compilando todo lo pueden obtener). Esto es necesario porque Twitter utiliza OAuth para la autentificación, y entonces tuve que registrar jAlarms como aplicación de Twitter; se necesita que Twitter valide que la aplicación está registrada y además que el usuario valide que dicha aplicación puede actualizar su status.

Entonces corren el TwitterAuth, que les da un URL temporal y les pide un PIN. El URL lo copian y lo pegan en el navegador donde crearon la cuenta de jalarmstest; les sale una página que les pide permiso para que jAlarms pueda modificar su status. Le dan en Allow (o Permitir si es que ya sale en español), y entonces les aparece un PIN gigantesco. Ese PIN lo copian del navegador y lo pegan en el TwitterAuth (que es un programa de línea de comando, así lo pueden correr hasta en el mero server donde ya van a hacer todo, ahorita verán por qué) y le dan ENTER. Con eso, les aparecen dos datos que deben copiar y guardar en un lugar SEGURO: El Access Token y el Token Secret.

Todo este relajito del TwitterAuth solamente lo tienen que hacer una vez por cada cuenta que quieren habilitar para jAlarms. Esos dos datos, AccessToken y TokenSecret, son las dos propiedades que necesita el TwitterChannel para poder actualizar el status de jalarmstest en Twitter. Y eso es todo; si ya tenían un AlarmSender configurado, solamente agregan el TwitterChannel con esas dos propiedades y a partir de entonces las alarmas que su aplicación envíe aparecerán también en el status del usuario jalarmstest para que las puedan ver los usuarios que siguen dicha cuenta.

Imagen de ezamudio

Origenes de alarma

Estoy agregando una funcionalidad a jAlarms que creo que le hace bastante falta: la capacidad de mandar mensajes a distintas personas según el origen de la alarma.

En aplicaciones grandes que tienen varios módulos, puede ser que las alarmas generadas por uno de los módulos le tengan que llegar a un grupo de personas (los encargados de dicho módulo) mientras que las alarmas generadas por otro módulo le deben llegar a un grupo distinto, y para el resto de la aplicación puedan llegar a un tercer grupo.

Actualmente cualquier alarma le llega al grupo definido en cada canal de alarma; por ejemplo en MailChannel le llegan las alarmas a los destinatarios del mensaje usado como template, mientras que en el MsnChannel le llegan las alarmas a todos los contactos del usuario usado para el envio de las mismas.

Con este cambio, se podrán definir destinos distintos para cada origen, así como los destinos default, para cuando la alarma no indica un origen o bien para cuando no hay un destino definido para dicho origen.

Y qué es el origen? bueno pues no es más que una simple cadena que indica el módulo del cual viene. Decidí esto en vez de poner una clase o crear un Enum o cualquier cosa así porque es algo fácil de definir por los usuarios de jAlarms (o sea los programadores de una aplicación) y permite que cada quien haga sus propias convenciones.

De este modo por ejemplo, en vez de simplemente llamar sender.sendAlarm("auxilio"), ahora puedo llamar desde el módulo A sender.sendAlarm("auxilio", "modA") mientras que desde el módulo B llamas sender.sendAlarm("socorro", "modB") y en el resto de la aplicación se puede simplemente invocar sender.sendAlarm("ayuda!", null) (aunque la verdad creo que sería recomendable SIEMPRE poner un módulo; de este modo, si el módulo no está definido en principio, se envían alarmas a los destinos por default de cada canal, pero después se puede comenzar a hacer más granular el envío de alarmas sin tener que recompilar nada).

En cada canal se pueden definir distintos destinos. Por ejemplo en el MailChannel se puede seguir usando solamente un template de ejemplo y entonces todas las alarmas saldrán siempre a los mismos destinatarios, pero en el MsnChannel se podrían definir unos destinos para el origen "modA" y otros distintos para el "modB"; para el resto de los orígenes se enviarán alarmas a todos los usuarios de la lista.

Espero que haya quedado clara la idea. Apenas estoy comenzando con la implementación de esto y mi primera duda es que todavía no sé si debería hacer que los canales recuerden las alarmas por origen (actualmente como no hay orígenes, solamente recuerdan los mensajes para no enviarlos tan seguido). De este modo la alarma "auxilio" para el origen "modA" se puede enviar aunque se pida inmediatamente después de enviar "auxilio" para el origen "modB", lo cual tiene sentido, porque a fin de cuentas, se tendrán distintos destinos configurados. Pero tendría que revisar si realmente hay una lista de destinos especiales configurados para el origen indicado; de lo contrario, cuenta como para los destinos default y aplican las reglas que existen actualmente (no se reenvia el mensaje en menos de X tiempo).

Imagen de skuarch

EJEMPLOS

soy relativamente nuevo en java, me podrias mostrar algun ejemplo??? o dime donde estan, gracias

Imagen de ezamudio

ligas

En el post viene la liga al sitio oficial.

Imagen de daynatem

Interesante

Yo vi un manejo de excepciones mediante smtp y sms y lo que hacian era extender de log4j o incluso modificando el propio código fuente de este framework el método FATAL que llamaba a un proceso para el envío del mensaje.

Osease que no quieres moverle mucho a tus proyectos puedes reimplementar el WARNING, FATAL o el que quieras de Log4j y meterle jAlarms

Imagen de ezamudio

plugin

Ya me habían hablado antes de la idea de hacer un plugin para Log4J. Hasta donde sé, Log4J ya tiene una manera de enviar un correo cuando ocurre una excepción por ejemplo (luxspes me lo comentó alguna vez), tal vez también para un FATAL. La ventaja de usar jAlarms en vez del envio directo de correo sería que la alarma se envíe por todos los canales configurados (mail, twitter, MSN, etc)

Imagen de paranoid_android

Muy Util

Muy útil, Cuando se diseña una arquitectura dificilmente se considera algo como esto, pero esta libreria permite agregar ese aspecto. ¡Felicidades en hora buena!

Imagen de Shadonwk

Saludos

Hola Zamudio te comento que desde ayer he estado leyendo sobre tu libreria, y llego el momento de echarla a andar, solo que me gustaria revisar algunas cuestiones contigo, y que me dieras el Vo.Bo. de si lo estoy haciendo correctamente:

en el aplication-context agregue:

        <!--    bean para el envio de correos-->

        <!--
                this channel will send alarms to the recipients defined in the mail
                template
        -->
        <bean id="mailChannel" class="com.solab.alarms.channels.MailChannel">
                <property name="javaMailSender" ref="javaMailSender" />
                <property name="mailTemplate">
                        <bean class="org.springframework.mail.SimpleMailMessage">
                                <property name="subject" value="My server application ALARM" />
                                <property name="from" value="do-not-reply@robertoleon.com.mx" />
                                <property name="text">
                                        <value>My application has send this ALARM: ${msg}
                                                This notification has been automatically sent, do not reply.
                </value>
                                </property>
                                <!-- This is obviously very important -->
                                <property name="to" value="rleon@robertoleon.com.mx" />
                        </bean>
                </property>
        </bean>
       
        <bean id="envioCorreo" class="com.solab.alarms.AlarmSender">
                <property name="channels">
                        <list>
                                <ref bean="mailChannel"/>                              
                        </list>
                        </property>
        </bean>

ahora para la dependencia de JavaMail, es correcto agregar esta libreria?
https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site...

Imagen de ezamudio

javamail

Pues sí, veo bien tu config, así tengo yo configurada una. Tu bean "javaMailSender" debe ser un org.springframework.mail.javamail.JavaMailSenderImpl. Para que esto funcione necesitas spring-core 3, mail.jar y activation.jar, pero estos dos últimos, si estás poniendo tu app en un contenedor JEE es casi seguro que ya están incluidos.

Imagen de AlexSnake

Muy interesante.

Es un tema que habría que revisar más a fondo para echarlo andar, espero no faltar en OpenTalks de javaMéxico cuando estes hablando sobre esto, y claro haber implentado algo para poder entender mas sobre ello.
Saludos.

Imagen de Shadonwk

Hola @Zamudio, por fin estoy

Hola @Zamudio, por fin estoy con el primer raund para echar a andar jAlarms te comento que encontre dos beans los cuales no los encuentra en el application-context y son:

 <property name="mailTemplate">
                        <bean class="org.springframework.mail.SimpleMailMessage">

<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"/>

y me muestra el siguiente error en el log.

Caused by: java.lang.NoClassDefFoundError: org/springframework/mail/SimpleMailMessage

aparentemente me están faltando algunas librerías, para ser exactos la de mail, ya tengo spring core en mi proyecto pero mail.jar y activation.jar no las hubico, aunque estoy corriendo mi app en Glasfish v 2.1.

Saludos.

Imagen de ezamudio

context-support

spring-context-support es donde viene lo de org.springframework.mail

Imagen de Shadonwk

Gracias, agregue la

Gracias, agregue la librería y efectivamente ahí viene org.springframework.mail, sin embargo me marca el siguiente error:

Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'channels' of bean class [com.solab.alarms.AlarmSender]: Bean property 'channels' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

mis declaraciones de los beans quedaron de la siguiente manera:

<!-- Correo  -->
         <bean id="mailChannel" class="com.solab.alarms.channels.MailChannel">
                <property name="javaMailSender" ref="javaMailSender" />
                <property name="mailTemplate">
                        <bean class="org.springframework.mail.SimpleMailMessage">
                                <property name="subject" value="My server application ALARM" />
                                <property name="from" value="do-not-reply@robertoleon.com.mx" />
                                <property name="text">
                                        <value>My application has send this ALARM: ${msg}
                                                This notification has been automatically sent, do not reply.
                                        </value>
                                </property>                                  
                                <property name="to" value="rleon@robertoleon.com.mx" />
                        </bean>
                </property>
        </bean>
       
        <bean id="envioCorreo" class="com.solab.alarms.AlarmSender">
                <property name="channels">
                        <list>
                                <ref bean="mailChannel"/>                              
                        </list>
                        </property>
        </bean>
        <bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"/>
        <!-- Termina correo -->

como puedes ver es parecido al que tenia en una de las respuestas anteriores solo agregue el bean javaMailSender...

Imagen de ezamudio

alarmChannels

Tienes acceso al código fuente y la documentación de javadoc... ahí dice que la propiedad es alarmChannels, no channels. En el ejemplo que puse en la página oficial también dice alarmChannels (revisé para estar seguro que no lo tuviera yo mal).

Imagen de Shadonwk

así es, nosé porque lo

así es, nosé porque lo cambie, debió ser en un ataque de locura... bien ahora hice un jsp que invoca al método enviar del siguiente BakingBean:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import com.solab.alarms.AlarmSender;

public class PruebaCorreoBean {
       
private AlarmSender envioCorreo;

       
        public void enviar(){
                envioCorreo.sendAlarm("Prueba envio correo");
                System.out.println("Enviado correo");
        }
       
        @Autowired @Qualifier ("envioCorreo")
        public void setEnvioCorreo(AlarmSender envioCorreo) {
                this.envioCorreo = envioCorreo;
        }

        public AlarmSender getEnvioCorreo() {
                return envioCorreo;
        }
}

bien acceso a la pantalla pulso el botón, y reviso el log...

INFO: Enviado correo

ahora reviso mi bandeja, y no hay nada.. también revise en spam pero tampoco, esto es raro, ya que el log no marca ningún error... tarda en llegar el correo?

Imagen de ezamudio

tarda?

No tengo manera de saber si tarda en llegar el correo, eso depende de tu servidor de correo. Si jAlarms envió realmente el correo no deberías ver nada en el log, pues MailChannel solamente imprime al log si hubo un error al intentar enviar el correo. Los errores comunes son que no se pueda conectar al servidor de correo, o que no pase la autenticación (el servidor SMTP rechaza el usuario/pass); hay ocasiones en que el servidor SMTP acepta la conexión y la autenticación pero simplemente no envía el correo porque no permite envio a usuarios de otros dominios.

Para que no tengas dudas de que jAlarms esté enviando la alarma, configura adicionalmente el TestChannel, ese simplemente imprime a STDOUT cuando se le pide enviar una alarma. Porque tu mensaje de "enviado correo" supongo que es del método enviar de tu JSP. Con el TestChannel sabrás si realmente jAlarms está recibiendo tu petición de enviar la alarma. Si el TestChannel no imprime nada, es que no recibió tu petición, y tal vez la bronca está en la configuración de tu app (tienes 2 instancias de AlarmSender o algo así), pero si el TestChannel imprime algo, la bronca seguramente está en la configuración del JavaMailSender de Spring.

Imagen de Shadonwk

jaja, como iba yo a saber

jaja, como iba yo a saber que:

 <bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"/>

necesitaba propiedades, hasta tenia cerrado el bean "/>" en fin soy un novato con esto, pero poco a poco estoy aprendiendo indague un poco en google y logre configurarlo ahora probé mi jsp, y en mi bandeja de entrada encontré esto:

(13:07:39) My application has send this ALARM: Prueba envio correo
                                               This notification has been automatically sent, do not reply.

Gracias por la ayuda, en verdad funciona, es una excelente aportación y ahora le daré un uso y te comento como estará funcionando, por cierto aquí mencionas que una de las mejoras es enviar correos a grupos de usuarios, para ello, tendrás algún tuto? o me toca clavarme a la documentación??

Imagen de ezamudio

grupos?

No sé bien dónde leíste eso. Si lo que quieres es enviar la misma alarma a varios usuarios en vez de uno solo, lo único que tienes que hacer es modificar el SimpleMailMessage que pasas como template al MailChannel; en vez de una cadena, le pasas una lista. Creo que las broncas que has tenido no han sido entonces con jAlarms sino con Spring y SMTP.

<property name="to"><list>
  <value>uncorreo@dominio.com</value>
  <value>otrocorreo@dominio.com</value>
  <value>otromas@etc.com</value>
</list></property>

Pero tal vez a lo que te refieres es a las fuentes de alarmas. Son una especie de filtro; es una vil cadena que defines en los canales que pones y que puedes usar cuando quieres enviar una alarma. Por ejemplo, suponte que tienes 2 módulos principales en tu aplicación y que quieres que las alarmas del módulo 1 le lleguen a unas personas y las alarmas del módulo 2 a otras personas, y además que se publiquen en twitter (en una cuenta que tiene tweets protegidos y que solamente unos cuantos usuarios autorizados pueden seguir).

Entonces puedes definir un MailChannel que en vez de tener la propiedad mailTemplate, usas la propiedad templatesBySource donde defines un SimpleMailMessage para el módulo 1 y otro distinto para el módulo 2 (incluyendo que puedes cambiar el mensaje, el remitente y por supuesto los destinos). Puedes además tener el mailTemplate configurado, no hay problema.

Cuando invoques sendAlarm("alarma 1", "m1"), entonces el MailChannel usará el SimpleMailMessage que tenga configurado para la fuente m1. Si invocas sendAlarm("otra cosa", "m2") entonces MailChannel usará el SimpleMailMessage configurado para la fuente m2. Si simplemente invocas sendAlarm("auxilio") entonces MailChannel va a usar el SimpleMailMessage de default, el configurado como mailTemplate.

Todo esto lo podrás ver en acción el sábado en las OpenTalks de javaMexico porque la primera conferencia es precisamente de jAlarms y ahora sí tendré tiempo de hacer una demo.

Imagen de Shadonwk

duda...

Hola @Zamudio, como bien dije en este mismo post el día de ayer logre hacer funcionar jAlarms, y el día de hoy planeo utilizar los filtros para las fuentes de alarmas, sin embargo viene a mi mente una pregunta "¿Se pueden parametrizar los correos de los destinatarios?" es decir si tengo un template de correo electrónico y se lo envió a alguien@algo.com, pero después ese mismo template de correo se lo quiero enviar a otroAlguien@alguien.com ¿se puede?

Imagen de ezamudio

no

Así como lo quieres, no se puede. Ten en cuenta que aunque solamente estás usando el canal de alarmas por mail, hay otros canales que ni siquiera manejan destinatarios (como el de MSN o el de Twitter). Pero puedes tener templates con distintos destinatarios configurados para distintas fuentes de alarmas como ya te expliqué, no voy a volver a teclear todo otra vez, lee el post anterior. Con eso puedes enviar distintas alarmas a distintos usuarios o grupos de usuarios (con el canal de mail).

Imagen de Shadonwk

y si..

Gracias, por ahora, me quedo hasta aquí, has pensado en modificar un poco tu aplicación para parametrizar los correos?, donde puedes aplicar esto?, se me ocurre que para un registro de usuarios, donde inmediatamente después de registrarse, se le envié un correo con su información de registro, ya se que jAlarms no esta echo para eso, pero seria uno mas de sus tantos usos... Por ahora intentare ver si puedo pasarle un correo mediante la ayuda de "SpEL"

Saludos.

Imagen de ezamudio

Exacto

el envío de un correo de registro no es tarea de jAlarms. Para eso simplemente crea tu propio SimpleMailMessage y envíalo directamente con el JavaMailSender. No ganas nada queriendo forzar el uso de un componente para algo que no fue diseñado.

Nuevamente: jAlarms no es un software para enviar correos. Es un software para enviar mensajes de alarma por distintos medios. Uno de esos medios es correo electrónico. Pero hay twitter, messenger, SMS, HTTP POST/GET, ejecución de un programa externo, etc. La manera de que ciertas alarmas lleguen a ciertos usuarios y otras lleguen a otros usuarios distintos, es por medio de las fuentes de alarma, que es un filtro que pueden implementar los distintos canales de distintas formas. El canal de correo tiene un SimpleMailMessage por cada fuente. El canal de MSN puede tener una lista de usuarios distinta por cada fuente. El de twitter solamente se le puede definir un canal y si lo tiene definido entonces solamente twitea alarmas de esa fuente e ignora las demás (y entonces puedes tener varias cuentas de twitter configuradas, cada una para distinta fuente). Para SMS funciona como con MSN, enviando los mensajes a los usuarios configurados para una fuente.

Imagen de Shadonwk

hola @Zamudio, sabes estoy

hola @Zamudio, sabes estoy tratando de configurar distintas fuentes, pero me envía el siguiente error:

Caused by: java.lang.IllegalStateException: Cannot convert value of type [org.springframework.mail.SimpleMailMessage] to required type [java.util.Map] for property 'templatesBySource': no matching editors or conversion strategy found

casi estoy seguro que la configuración la tengo mal, pero la pongo de todas maneras:

<property name="templatesBySource">
                        <bean class="org.springframework.mail.SimpleMailMessage">
                                <property name="subject" value="My server application ALARM" />
                                <property name="from" value="do-not-reply@robertoleon.com.mx" />
                                <property name="text">
                                        <value>Template 1: ${msg}
                                                This notification has been automatically sent, do not reply.
                </value>
                                </property>
                                 
                                <property name="to" value="#{pruebaCorreoBean.correoE}" />
                        </bean>
                </property>
Imagen de ezamudio

mal

Si ves el javadoc de MailChannel verás que la propiedad templatesBySource es un mapa. Las llaves son los nombres de las fuentes de alarmas y los valores son SimpleMailMessages. Si quieres definir un solo template para todas las alarmas debes usar template, no templatesBySource.

Imagen de Shadonwk

ejemplo

correcto, acabo de revisar la documentación y ahora me hace sentido el error, sin embargo no tengo mucha idea de como hacerlo mediante xml, ¿ podrías regalarme un ejemplo sencillo?

Imagen de ezamudio

mapa

se define como cualqueir mapa de XML en Spring. Las llaves son strings y los valores son SimpleMailMessages.

Imagen de Shadonwk

es correcto?

me quedo algo mas o menos asi:

 <property name="templatesBySource">
                   <map>  
                            <entry>  
                                <key><value>uno</value></key>  
                                <value>
                                                <bean class="org.springframework.mail.SimpleMailMessage">
                                                           <property name="subject" value="My server application ALARM" />
                                                           <property name="from" value="do-not-reply@robertoleon.com.mx" />
                                                           <property name="text">
                                                                      <value>TEMPLATE 1ALARM: ${msg}
                                                                              This notification has been automatically sent, do not reply.
                                                                     </value>
                                                            </property>
                                                            <property name="to" value="#{pruebaCorreoBean.correoE}" />
                                                 </bean>
                                 </value>  
                            </entry>                       
                        </map>  
</property>
Imagen de ezamudio

si

asi esta bien. hay una sintaxis simplificada para entradas de un mapa en la config XML de Spring: <entry key="x" value="z"> o si el valor va a ser un bean como en este caso, <entry key="x">...</entry> y el bean lo defines dentro de ese segmento. También puedes poner "ref" en vez de "value" para que el valor de esa entrada en el mapa sea una referencia a un bean definido en otra parte. Pero esas ya son cosas de Spring, no de jAlarms.

Imagen de Shadonwk

Gracias, probado, y

Gracias, probado, y funcionando =), y ahora espero verlo funcionando directamente del creador...

¿Tiempo de proceso?

Hola,

Me parece muy interesante y muchas gracias por crear el proyecto, ya me descargo las fuentes. Sobre este tema, trabajé para una gran corporación turística de reservas que como las demás, cada vez se integran más unas con otras mediante WS. Por si sirve de interés, os explico el enfoque que adoptamos; como cada sistema es muy particular y se procesan miles de mensajes diarios, detectar los fallos de integración o interpretación de mensajes era muy importante, por lo que resolvimos este problema mediante las "nuevas" colecciones concurrentes de 1.5 o colas sincronizadas. Los interpretadores de mensajes al detectar un error, invocaban una clase genérica que depositaba el objeto de notificación según destino en la cola correspondiente, procesada a posteriori por otro hilo consumidor de notificaciones. Hubiéramos preferido un JMS pero no pudo ser (en casa del herrero cuchillo de palo) y ésto fue lo más parecido sin esta infraestructura. Lo interesante es que teníamos otros hilos monitores de colas que avisaban de la sobrecarga de las mismas, y activaban en los consumidores si debían descartar notificaciones o utilizar funciones de correlación para detectar una progresión insostenible de recepción de notificaciones. Esto último, evitaba notificar 16000 veces del mismo error cuando tienes varios servidores procesando mensajes similares, lo que podría matarnos la cuenta del TWITTER ;) y por lo que creo que sería interesante añadir esto a jAlarms si es que ya no lo tiene. En fin, que de nuevo gracias por compartir el proyecto. Un saludo.

Imagen de ezamudio

lo tiene

Tal vez no tan sofisticado como lo que mencionas pero desde el principio jAlarms tiene un mecanismo para evitar mensajes repetidos. Cada canal tiene un parámetro que es el tiempo mínimo en milisegundos para reportar la misma alarma. Cada que mandas un mensaje de alarma se guarda la fecha en que fue enviado dicho mensaje para evitar enviar demasiadas alarmas repetidas, porque no es bueno saturar el canal que sea (tener 16000 correos en tu cuenta tampoco es muy práctico que digamos).

Plugin para Grails

Hola!
Estoy intentando implementar el plugin de jalarms para grails, no se si me puedas ayudar con eso. En teoria solo instalas el plugin de grails y puedes usar el metodo sendAlarm(String texto) no? el caso es que no me imprime nada.
Tengo que configurar los canales? o ya viene por defecto configurado algun canal?

De antemano gracias por tu ayuda.

Imagen de ezamudio

tienes que configurarlos

El método sendAlarm que se inyecta a los controladores (y creo que servicios, no recuerdo ahorita) solamente invoca el método sendAlarm de la instancia de AlarmSender que se crea al poner el plugin, pero no viene ningún canal configurado (eso no lo hace el plugin porque de verdad ya es algo muy específico de tu aplicación).

De entrada puedes probar configurando simplemente un TestChannel, en tu grails-app/conf/spring/resources.groovy. O puedes agregar uno con mail si quieres o con línea de comando...

beans={
  canalPrueba(com.solab.alarms.channels.TestChannel)

  //Este puede ser divertido si estás en una Mac
  canalCLI(com.solab.alarms.channels.CommandLineChannel) {
    command='/usr/bin/say'
  }
}

Gracias!

Gracias ya quedo, al menos con el TesChannel ahora mismo hare pruebas con el canal de mail. El que no pude probar fue el de canalCLI, pero me dio curiosidad, a ver cuando puedo probarlo :).

Imagen de beto.bateria

Instalar JAlarmas sin Spring.

Que tal ezamudio, quiero implementar JAlarms en una aplicacion, esta aplicacion no tiene frameworks o librerias y me gustaria que asi permaneciera, se ejecuta en un servidor tomcat. En el sitio de JAlarms se da un ejemplo para instalar la app con Spring, ¿Hay alguna forma de hacerlo sin ningun framework, solo con las librerias que ofrece java?

Imagen de ezamudio

claro

Solamente tienes que crear todos los componentes y conectarlos.

Imagen de beto.bateria

Gracias, voy a investigar.

Gracias, voy a investigar.

Imagen de benek

Así es, con instanciamientos

Así es, con instanciamientos comunes y corrientes en vez de Spring don Beto.

Imagen de beto.bateria

Saludos: Cree este codigo:  

Saludos:
Cree este codigo:

        ArrayList<AlarmChannel> channels = new ArrayList<AlarmChannel>();

        TestChannel testChannel = new TestChannel();
        MsnChannel msnChannel = new MsnChannel();
        msnChannel.setUsername("beto.bateria@javamexico.com");
        msnChannel.setPassword("createand");
        msnChannel.addContact("escuela@hotmail.com");

        channels.add(testChannel);
        channels.add(msnChannel);
       
        AlarmSenderImpl alarmSender = new AlarmSenderImpl();
        alarmSender.setAlarmChannels(channels);
        alarmSender.sendAlarm("ya estuvo");

TestChannel ya manda imprimir a STDOUT la cadena "ya estuvo". Supongo que de la cuenta de messenger beto.bateria@javamexico.com se manda a escuela@hormail.com el mismo mensaje.

¿Hay que tener tener otras consideraciones, tales como cerrar algun recurso utilizado?

Gracias por la ayuda.

Imagen de beto.bateria

Para los que quieran instalar

Para los que quieran instalar jAlarms. es necesario tener estas librerias:

Commons Codec Base64 http://commons.apache.org/codec/
HttpClient http://hc.apache.org/downloads.cgi
HttpCore http://hc.apache.org/downloads.cgi
jAlarms http://sourceforge.net/projects/jalarms/files/jAlarms/1.6.1/
jml http://sourceforge.net/projects/java-jml/files/java-jml/jml-1.0b4/
SLF4J http://www.slf4j.org/download.html

Y estos son los .jar que utilice para implementar el servicio:

commons-codec-1.6.jar
commons-logging-1.1.1.jar
fluent-hc-4.2.jar
httpclient-4.2.jar
httpclient-cache-4.2.jar
httpcore-4.2.1.jar
httpcore-4.2.jar
httpcore-ab-4.2.1.jar
httpcore-nio-4.2.1.jar
httpmime-4.2.jar
jalarms-channels-1.6.1.jar
jalarms-core-1.6.1.jar
jalarms-remote-1.6.1.jar
jml-1.0b4-full.jar
slf4j-api-1.6.6.jar
slf4j-ext-1.6.6.jar
slf4j-migrator-1.6.6.jar
slf4j-simple-1.6.6.jar
Imagen de beto.bateria

Ayuda al instalar jAlarms

Con el codigo arriba escrito, no se manda aun ningun mensaje, pero pasa lo siguiente:

Al ejecutar el codigo arriba mostrado, el cual se ejecuta en un servlet, pasa los siguiente(espero me puedan ayudar):

- Se muestra una hoja de error en donde indica que se agrege el archivo commons-chain-1.2.jar(pero ya se encuentra en las librerias). indicando tambien lo siguiente:

// Compiled from ChainBase.java (version 1.3 : 47.0, super bit)
public class org.apache.commons.chain.impl.ChainBase implements org.apache.commons.chain.Chain {

Y al momento de ejecutar la siguiente linea de codigo:

msnChannel.addContact("escuela@hotmail.com");

El IDE muestra el siguiente mensaje:

22385 [http-8080-2] INFO com.solab.alarms.channels.MsnChannel - MsnChannel adding contact escuela@hotmail.com

Y despliega siguiente error:

21/06/2012 10:33:21 AM org.apache.struts.chain.commands.AbstractExceptionHandler execute
ADVERTENCIA: Unhandled exception
java.lang.NullPointerException
        at com.solab.alarms.channels.MsnChannel.addContact(MsnChannel.java:153)
        at com.erp.controller.Products.execute(Products.java:38)
        at org.apache.struts.chain.commands.servlet.ExecuteAction.execute(ExecuteAction.java:58)
        at org.apache.struts.chain.commands.AbstractExecuteAction.execute(AbstractExecuteAction.java:67)
        at org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:51)
        at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
        at org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:305)
        at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
        at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)
        at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
        at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:449)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
        at java.lang.Thread.run(Unknown Source)
21/06/2012 10:33:21 AM org.apache.struts.chain.commands.ExceptionCatcher postprocess
ADVERTENCIA: Exception from exceptionCommand 'servlet-exception'
java.lang.NullPointerException
        at com.solab.alarms.channels.MsnChannel.addContact(MsnChannel.java:153)
        at com.erp.controller.Products.execute(Products.java:38)
        at org.apache.struts.chain.commands.servlet.ExecuteAction.execute(ExecuteAction.java:58)
        at org.apache.struts.chain.commands.AbstractExecuteAction.execute(AbstractExecuteAction.java:67)
        at org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:51)
        at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
        at org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:305)
        at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
        at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)
        at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
        at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:449)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
        at java.lang.Thread.run(Unknown Source)
21/06/2012 10:33:21 AM org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Servlet.service() para servlet action lanzó excepción
java.lang.NullPointerException
        at com.solab.alarms.channels.MsnChannel.addContact(MsnChannel.java:153)
        at com.erp.controller.Products.execute(Products.java:38)
        at org.apache.struts.chain.commands.servlet.ExecuteAction.execute(ExecuteAction.java:58)
        at org.apache.struts.chain.commands.AbstractExecuteAction.execute(AbstractExecuteAction.java:67)
        at org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:51)
        at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
        at org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:305)
        at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
        at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)
        at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
        at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:449)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
        at java.lang.Thread.run(Unknown Source)
Imagen de ezamudio

libs

Las bibliotecas adicionales dependen de los canales que quieras utilizar. Por ejemplo para el canal de pruebas y para el de twitter no necesitas más que jalarms-core y slf4j. Pero para el de messenger necesitas JML. Los de http creo que son para XMPP o nagios algo asi.

Imagen de beto.bateria

Pues voy a seguir buscando,

Pues voy a seguir buscando, porque me marca el error en la libreria commons-chain-1.2.jar.