JBoss scheduling con data settata dinamicamente
Wednesday 27 February, 2008 at 15:52
Se si desidera avviare dei jobs in istanti di tempo settati dinamicamente e’ necessario sfruttare quanto di buono e’ offerto dai componenti JMX di JBoss.
Si parte con la creazione di un TimerMBean e per farlo si hanno tre possibilità:
- Si aggiunge la seguente riga al file jboss-service.xml nella directory conf dell’istanza del server:
<mbean code="javax.management.timer.Timer" name="MarcocciaNet:service=myTimer"/>
- Si crea come servizio di un’applicazione di deploy configurando un file di service (per es. mytimer-service.xml) con il seguente contenuto:
<?xml version="1.0" encoding="UTF-8"?> <server> <mbean code="javax.management.timer.Timer" name="MarcocciaNet:service=myTimer"/> </server>
lo si mette nella root dell’ear e lo si richiama nel jboss-app.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jboss-app PUBLIC "-//JBoss//DTD J2EE Application 1.4//EN" "http://www.jboss.org/j2ee/dtd/jboss-app_4_0.dtd"> <jboss-app> <module> <service>mytimer-service.xml</service> </module> [...] </jboss-app> - Si crea il servizio programmaticamente:
MBeanServer server = MBeanServerFactory.createMBeanServer(); ObjectInstance timer = server.createMBean( "javax.management.timer.Timer", new ObjectName( "MarcocciaNet", "service", "myTimer" )); server.invoke( timer.getObjectName(), "start", new Object[] {}, new String[] {});
La prima soluzione la trovo un pochino invasiva: di norma non è saggio mettere le mani in un file in cui ci sono le configurazioni di tutti gli altri servizi standard di un application server. La terza soluzione richiede attenzione soprattutto nel momento in cui è necessario decidere dove piazzare la parte di codice, che va fatto prima della registrazione listener e delle eventuali notifiche.
La seconda soluzione è la migliore: il servizio è deploiato con l’intera applicazione e prima di ogni altro eventuale componente enterprise. Inoltre all’atto pratico questa soluzione si dimostrerà senza dubbio più versatile.
Una volta istanziato il TimerMBean è necessario agganciare uno o più listener e per farlo è necessario invocare il metodo addNotificationListener sull’istanza dell’MBeanServer. Di seguito un esempio con listener anonimo:
NotificationListener notificationListener = new NotificationListener() {
public void handleNotification(Notification notification, Object handback) {
logWriter.debug("Notification received!");
logWriter.debug("UserObject: " + notification.getUserData());
}
};
try {
ObjectName objectName = new ObjectName("MarcocciaNet:service=myTimer");
// find the local MBeanServer
MBeanServer server = MBeanServerLocator.locateJBoss();
server.addNotificationListener(objectName, notificationListener, null, null);
} catch (MalformedObjectNameException ex) {
// manage
} catch (InstanceNotFoundException ex) {
// manage
}
Il terzo parametro di addNotificationListener permette al listener di filtrare le notifiche tramite un oggetto NotificationFilter, mentre il quarto parametro è un oggetto di “handback”, ovvero quello ritornato al listener all’arrivo di una notifica.
Adesso che abbiamo anche il listener è possibile inviare le notifiche:
public void sendNotification(Object userData, Date date){
try {
InitialContext initialContext = new InitialContext();
RMIAdaptor adaptor = (RMIAdaptor) initialContext.lookup("jmx/invoker/RMIAdaptor");
ObjectName objectName = new ObjectName("MarcocciaNet:service=myTimer");
if (adaptor != null && adaptor.isRegistered(objectName)) {
adaptor.invoke(
objectName,
"addNotification",
new Object[]{
"oneShotNotification",
"One shot notification sample",
userData,
date},
new String[]{
String.class.getName(),
String.class.getName(),
Object.class.getName(),
Date.class.getName()});
} else {
logWriter.debug("---- JNDI Name error: " + adaptor + " ----");
// manage
}
} catch (NamingException ex) {
// manage
} catch (MalformedObjectNameException ex) {
// manage
} catch (IOException ex) {
// manage
} catch (InstanceNotFoundException ex) {
// manage
} catch (MBeanException ex) {
// manage
} catch (ReflectionException ex) {
// manage
}
}
Una volta messo insieme i pezzi è possibile centralizzare il tutto (registrazione/rimozione listener ed invio notifiche) creando un servizio (sar) ad hoc ed esponendo i metodi di javax.management.timer.Timer che non sono esposti dal TimerMBean:
public interface MyTimerMBean extends TimerMBean {
public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback);
public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException;
}
public class MyTimer extends Timer implements MyTimerMBean {
public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback){
super.addNotificationListener(listener, filter, handback)
}
public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
super.removeNotificationListener(listener);
}
}
Quest’ultima configurazione apre un’ampia gamma di scenari: è possibile gestire di un pool di listener, potento fare override di start() e’ possibile registrare un listener a startup e così via…
Alla prossima
Buzz This Post
Delicious
Digg This Post
Ping This Post
Entry Filed under: jboss,scheduling
1 Comment Add your own
1. mike | Thursday 2 September, 2010 at 16:18
ma uno zip con un esempio completo no?
Leave a Comment
Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
Trackback this post | Subscribe to the comments via RSS Feed