poniedziałek, 20 października 2008

Rozsyłanie sygnałów w JMX

Kontynuujemy zabawę z JMX :) W poprzednim wpisie stworzyliśmy aplikację która umożliwiała zmianę parametrów mziaren 'na odległość'. W tym poście wzbogacimy ją o funkcję rozsyłania sygnałów przy spełnieniu pewnych warunków - u nas będzie to sygnał o przekroczenie limitu użytkowników.
Kody źródłowe z poprzedniego wpisu można pobrać: tutaj (projekty w NetBeans IDE).

Zacznijmy od tego jak reprezentowany jest sygnał. Kiedy go wysyłamy przesyłany jest obiekt typu javax.management.Notification, któremu w konstruktorze możemy podać takie parametry jak typ(String), źródło(Object), numer sygnału(long), czas (long) oraz wiadomość (String).

MBean który chce wysyłać sygnały musi implementować interfejs NotificationEmitter jednak w praktyce klasa ziarna dziedziczy po klasie NotificationBroadcasterSupport, która udostępnia kilka użytecznych metod - właśnie tej klasy użyjemy w przykładzie.
No to przejdźmy do implementacji...

Serwer
Lista modyfikacji które należy wprowadzić w klasie serwera:
- klasa powinna dziedziczyć po javax.management.NotificationBroadcasterSupport
- dodajemy pole:
private static final String TYPE_LIMIT_USERS = "USERS_SERVER_LIMIT";
będzie to nasz typ komunikatu. Można to zrealizować trochę inaczej tworząc podklasę klasy Notification i w niej opakować takie informację (przykładem takiej klasy jest np. AttributeChangeNotification).
- dodajemy pole
private int notifyCounter = 0;
które będzie licznikiem wysyłanych sygnałów.

W konstruktorze klasy dodamy klasę anonimową (wątek) która będzie sprawdzać co określony okres czasu czy przekroczono maksymalną liczbę użytkowników. Jeśli taka sytuacja nastąpi wysłany zostanie sygnał do wszystkich "słuchaczy" - czyli klientów obserwujących to mziarno.

Wysłanie sygnału odbywa się poprzez wywołanie metody sendNotification którą odziedziczyliśmy.

W kodzie pojawia się dodatkowy wątek który dla testów zmienia wartość users na większy niż limit aby przetestować działanie całości.

Oto kompletny kod Server.java:
package com.blogspot.wookasz.jmxtutorial;

import java.util.Random;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;

public class Server extends NotificationBroadcasterSupport
implements ServerMBean {

private static final String TYPE_LIMIT_USERS = "USERS_SERVER_LIMIT";
private int notifyCounter = 0;
private int users = 0;
private int limit = 5;
private Thread notificationThread;

public Server() {
Random rnd = new Random();
users = rnd.nextInt(100);

final Server serverObj = this;

notificationThread = new Thread() {

@Override
public void run() {
try {
while (!Thread.interrupted()) {
Thread.sleep(1000 * 10);
System.out.println("Sprawdzanie");
if (limit < users) {
Notification notify =
new Notification(TYPE_LIMIT_USERS,
serverObj,
++notifyCounter,
System.currentTimeMillis(),
"Przekroczono dopuszczalny limit użytkowników na serwerze");
System.out.println("Wysyłanie");
sendNotification(notify);
}
}
} catch (InterruptedException ex) {
}
}
};
notificationThread.start();

/****************************************/
// wątek potrzebny do przykładu
Thread test = new Thread() {

@Override
public void run() {
try {
Thread.sleep(100);
System.out.println("Zmiana");
users = limit + 1;
} catch (InterruptedException ex) {
}
}
};
test.start();
}

public void setUsersLimit(int limit) {
this.limit = limit;
System.out.println("Limit uzytkowników zmieniono na: " + limit);
}

public int getUsers() {
return users;
}
}

Reszta plików pozostaje bez zmian.

Klient
Klasa klienta aby mogła odebrać sygnał musi implementować interfejs NotificationListener który wymusza implementację metody handleNotification.
Parametrami tej metody są:
- Notification notification - sygnał przychodzący
- Object handback - obiekt przekazywany w trakcie wywoływania metody addListener - rejestrowania słuchacza. Jest to obiekt pomocniczy.
Po zaimplementowaniu obiektu nasłuchującego należy go zarejestrować wywołując metodę addNotificationListener klasy typu MBeanServerConnection.
Metoda ta przyjmuje następujące parametry:
- ObjectName name - nazwa mziarna które emituje sygnały
- NotifiactionListener listener - obiekt nasłuchujący który rejestrujemy
- NotificationFilter - filtr sygnałów
- Object handback - obiekt pomocniczy przekazywany do obiektu nasłuchującego

No i to by było na tyle :)
Kod klasy nasłuchującej ClientListener.java:
package com.blogspot.wookasz.jmxtutorial;

import java.util.Date;
import javax.management.*;

public class ClientListener implements NotificationListener {

public void handleNotification(Notification notification,
Object handback) {

System.out.println("*** Odebrano sygnał! ****");
System.out.println("Wiadomość: " + notification.getMessage());
System.out.println("Nadany o godzinie: " + new Date(notification.getTimeStamp()));
}
}

Do klasy klienta dodano tylko następujące linie rejestrujące obiekt nasłuchujący:
ClientListener listener = new ClientListener();
server.addNotificationListener(name, listener, null, null);

Pełne kody źródłowe można pobrać: tutaj.

Zapraszam do komentowania ;-)

Brak komentarzy:

Prześlij komentarz