KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mx4j > examples > mbeans > legacy > DynamicLegacyService


1 /*
2  * Copyright (C) The MX4J Contributors.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the MX4J License version 1.0.
6  * See the terms of the MX4J License in the documentation provided with this software.
7  */

8
9 package mx4j.examples.mbeans.legacy;
10
11 import java.lang.reflect.Field JavaDoc;
12 import java.lang.reflect.Method JavaDoc;
13 import javax.management.ListenerNotFoundException JavaDoc;
14 import javax.management.MBeanAttributeInfo JavaDoc;
15 import javax.management.MBeanNotificationInfo JavaDoc;
16 import javax.management.MBeanOperationInfo JavaDoc;
17 import javax.management.MBeanParameterInfo JavaDoc;
18 import javax.management.Notification JavaDoc;
19 import javax.management.NotificationBroadcaster JavaDoc;
20 import javax.management.NotificationBroadcasterSupport JavaDoc;
21 import javax.management.NotificationFilter JavaDoc;
22 import javax.management.NotificationListener JavaDoc;
23
24 import mx4j.AbstractDynamicMBean;
25
26 /**
27  * The wrapper DynamicMBean for exposing the legacy service in a non-invasive way. <br>
28  * This MBean emits notifications when the legacy service starts its activity and when it stops it.
29  * Furthermore, when the legacy service is running, it displays the number of threads that the
30  * legacy service is using to perform its activity. <br>
31  * Note how the {@link LegacyService} is completely unaware of JMX, and even if it has private fields
32  * and methods (the legacy service was designed without knowledge of JMX), it is possible to
33  * expose them (via reflection) in JMX. <br>
34  * This MBean is divided in two parts, the implementation one and the JMX one. Note how the JMX
35  * part, thanks to {@link AbstractDynamicMBean}, is very simple even if it is a DynamicMBean.
36  *
37  * @version $Revision: 1.4 $
38  */

39 public class DynamicLegacyService extends AbstractDynamicMBean implements NotificationBroadcaster JavaDoc
40 {
41    //
42
// Implementation Part
43
//
44

45    private LegacyService service;
46    private Thread JavaDoc statusThread;
47
48    public DynamicLegacyService(LegacyService service)
49    {
50       this.service = service;
51
52       statusThread = new Thread JavaDoc(new Runnable JavaDoc()
53       {
54          public void run()
55          {
56             monitorStatus();
57          }
58       });
59    }
60
61    /**
62     * Starts monitoring the legacy service, and starts as well the legacy service
63     *
64     * @see #isRunning
65     */

66    public void start()
67    {
68       // Start the thread that monitors the status of the service
69
statusThread.start();
70
71       // We remap the 'start' method as defined by JMX to the 'execute' method of the legacy service
72
service.execute();
73    }
74
75    /**
76     * Returns whether the legacy service has woken up and it is running or not.
77     */

78    public boolean isRunning()
79    {
80       // The method 'isRunning' is private in the legacy service, so here we use reflection tricks
81
try
82       {
83          Class JavaDoc cls = service.getClass();
84          Method JavaDoc method = cls.getDeclaredMethod("isRunning", new Class JavaDoc[0]);
85          method.setAccessible(true);
86          Boolean JavaDoc result = (Boolean JavaDoc)method.invoke(service, new Object JavaDoc[0]);
87          return result.booleanValue();
88       }
89       catch (Exception JavaDoc ignored)
90       {
91          ignored.printStackTrace();
92          return false;
93       }
94    }
95
96    /**
97     * Returns the number of threads that the legacy service is using to perform its job when it
98     * wakes up.
99     */

100    public int getThreadCount()
101    {
102       // There is no a direct mapping of the thread count in the legacy service
103
// We use again reflection tricks, calling LegacyService.group.activeCount()
104
try
105       {
106          Class JavaDoc cls = service.getClass();
107          Field JavaDoc field = cls.getDeclaredField("group");
108          field.setAccessible(true);
109          ThreadGroup JavaDoc group = (ThreadGroup JavaDoc)field.get(service);
110          return group.activeCount();
111       }
112       catch (Exception JavaDoc ignored)
113       {
114          ignored.printStackTrace();
115          return 0;
116       }
117    }
118
119    /**
120     * Monitors the status of the legacy service, every 50 ms, to see if it has woken up
121     * and it is running. <br>
122     * When the legacy service starts and stops its job, a notification is emitted.
123     */

124    private void monitorStatus()
125    {
126       boolean wasRunning = false;
127       while (true)
128       {
129          boolean isRunning = isRunning();
130          if (wasRunning ^ isRunning)
131          {
132             Notification JavaDoc notification = new Notification JavaDoc("legacy.status.running." + isRunning, this, 0, "Legacy Service Status: " + isRunning);
133             broadcaster.sendNotification(notification);
134             wasRunning = isRunning;
135          }
136          else
137          {
138             if (isRunning) System.out.println("Threads: " + getThreadCount());
139          }
140
141          // Monitor every 50 ms
142
try
143          {
144             Thread.sleep(50);
145          }
146          catch (InterruptedException JavaDoc ignored)
147          {
148          }
149       }
150    }
151
152    //
153
// JMX Part
154
//
155

156    private NotificationBroadcasterSupport JavaDoc broadcaster = new NotificationBroadcasterSupport JavaDoc();
157
158    protected MBeanAttributeInfo JavaDoc[] createMBeanAttributeInfo()
159    {
160       return new MBeanAttributeInfo JavaDoc[]
161       {
162          new MBeanAttributeInfo JavaDoc("Running", "boolean", "The running status of the Legacy Service", true, false, true),
163          new MBeanAttributeInfo JavaDoc("ThreadCount", "int", "The number of running threads", true, false, false)
164       };
165    }
166
167    protected MBeanOperationInfo JavaDoc[] createMBeanOperationInfo()
168    {
169       return new MBeanOperationInfo JavaDoc[]
170       {
171          new MBeanOperationInfo JavaDoc("start", "Start the Legacy Service", new MBeanParameterInfo JavaDoc[0], "void", MBeanOperationInfo.ACTION)
172       };
173    }
174
175    protected MBeanNotificationInfo JavaDoc[] createMBeanNotificationInfo()
176    {
177       return getNotificationInfo();
178    }
179
180    public void addNotificationListener(NotificationListener JavaDoc listener, NotificationFilter JavaDoc filter, Object JavaDoc handback)
181    {
182       broadcaster.addNotificationListener(listener, filter, handback);
183    }
184
185    public MBeanNotificationInfo JavaDoc[] getNotificationInfo()
186    {
187       return new MBeanNotificationInfo JavaDoc[]
188       {
189          new MBeanNotificationInfo JavaDoc
190                  (new String JavaDoc[]{"legacy.status.running.true", "legacy.status.running.false"},
191                   Notification JavaDoc.class.getName(),
192                   "Notifications on the status of the Legacy Service")
193       };
194    }
195
196    public void removeNotificationListener(NotificationListener JavaDoc listener) throws ListenerNotFoundException JavaDoc
197    {
198       broadcaster.removeNotificationListener(listener);
199    }
200 }
201
Popular Tags