1 /***
2 * Copyright 2003-2010 Terracotta, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package net.sf.ehcache.management;
18
19 import net.sf.ehcache.AbstractCacheTest;
20 import net.sf.ehcache.Ehcache;
21 import net.sf.ehcache.Element;
22 import net.sf.ehcache.config.Configuration;
23 import net.sf.ehcache.config.ConfigurationFactory;
24 import net.sf.ehcache.constructs.blocking.BlockingCache;
25 import org.junit.After;
26
27 import static org.junit.Assert.assertEquals;
28 import static org.junit.Assert.assertNotNull;
29 import static org.junit.Assert.assertNull;
30
31 import org.junit.Before;
32 import org.junit.Test;
33
34 import javax.management.JMException;
35 import javax.management.MBeanAttributeInfo;
36 import javax.management.MBeanInfo;
37 import javax.management.MBeanServer;
38 import javax.management.MBeanServerConnection;
39 import javax.management.MBeanServerFactory;
40 import javax.management.ObjectName;
41 import javax.management.remote.JMXConnector;
42 import javax.management.remote.JMXConnectorServer;
43 import javax.management.remote.JMXConnectorServerFactory;
44 import javax.management.remote.JMXServiceURL;
45 import java.io.File;
46 import java.io.IOException;
47 import java.rmi.registry.LocateRegistry;
48 import java.util.Iterator;
49 import java.util.List;
50 import java.util.Set;
51
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55 /***
56 * These tests use the JDK1.5 platform mbean server
57 * To interactively examine behaviour, add a Thread.sleep(...) and add -Dcom.sun.management.jmxremote to the java
58 * invocation.
59 * <p/>
60 * To see ehcache specific types in the JMX client add the ehcache.jar to the classpath.
61 * e.g. to avoid the "Unavailable" message in jconsole caused by ClassNotFound add:
62 * jconsole -J-Djava.class.path=core/target/classes
63 *
64 * @author Greg Luck
65 * @version $Id: ManagementServiceTest.html 13146 2011-08-01 17:12:39Z oletizi $
66 */
67 public class ManagementServiceTest extends AbstractCacheTest {
68
69 private static final Logger LOG = LoggerFactory.getLogger(ManagementServiceTest.class.getName());
70 private static final int OBJECTS_IN_TEST_EHCACHE = 46;
71 private MBeanServer mBeanServer;
72
73
74 /***
75 * setup test
76 */
77 @Override
78 @Before
79 public void setUp() throws Exception {
80 super.setUp();
81 mBeanServer = createMBeanServer();
82 }
83
84 private MBeanServer create14MBeanServer() {
85 return MBeanServerFactory.createMBeanServer("SimpleAgent");
86 }
87
88 /***
89 * teardown
90 */
91 @Override
92 @After
93 public void tearDown() throws Exception {
94 super.tearDown();
95
96 assertEquals(0, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
97 }
98
99
100 /***
101 * Integration test for the registration service
102 */
103 @Test
104 public void testRegistrationServiceFourTrue() throws Exception {
105 ManagementService.registerMBeans(manager, mBeanServer, true, true, true, true, true);
106 assertEquals(OBJECTS_IN_TEST_EHCACHE, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
107 }
108
109 /***
110 * Integration test for the registration service
111 */
112 @Test
113 public void testRegistrationServiceFourTrueUsing14MBeanServer() throws Exception {
114 mBeanServer = create14MBeanServer();
115 ManagementService.registerMBeans(manager, mBeanServer, true, true, true, true, true);
116 assertEquals(OBJECTS_IN_TEST_EHCACHE, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
117 }
118
119
120 /***
121 * Integration test for the registration service using a contructed ManagementService as would be done
122 * by an IoC container.
123 */
124 @Test
125 public void testRegistrationServiceFourTrueUsing14MBeanServerWithConstructorInjection() throws Exception {
126 mBeanServer = create14MBeanServer();
127 ManagementService managementService = new ManagementService(manager, mBeanServer, true, true, true, true, true);
128 managementService.init();
129 assertEquals(OBJECTS_IN_TEST_EHCACHE, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
130 }
131
132 /***
133 * Integration test for the registration service
134 */
135 @Test
136 public void testRegistrationServiceListensForCacheChanges() throws Exception {
137 ManagementService.registerMBeans(manager, mBeanServer, true, true, true, true, true);
138 assertEquals(OBJECTS_IN_TEST_EHCACHE, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
139 manager.addCache("new cache");
140 assertEquals(OBJECTS_IN_TEST_EHCACHE + 3, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
141 manager.removeCache("sampleCache1");
142 assertEquals(OBJECTS_IN_TEST_EHCACHE, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
143
144 }
145
146 /***
147 * Integration test for the registration service
148 */
149 @Test
150 public void testMultipleCacheManagers() throws Exception {
151 ManagementService.registerMBeans(manager, mBeanServer, true, true, true, true, true);
152 assertEquals(OBJECTS_IN_TEST_EHCACHE, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
153 File file = new File(AbstractCacheTest.SRC_CONFIG_DIR + "ehcache.xml");
154 Configuration configuration = ConfigurationFactory.parseConfiguration(file);
155 net.sf.ehcache.CacheManager secondCacheManager = new net.sf.ehcache.CacheManager(configuration);
156 ManagementService.registerMBeans(secondCacheManager, mBeanServer, true, true, true, true, true);
157 assertEquals(OBJECTS_IN_TEST_EHCACHE + 19, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
158 secondCacheManager.shutdown();
159 assertEquals(OBJECTS_IN_TEST_EHCACHE, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
160
161
162
163 }
164
165 /***
166 * Checks that Statistics updates
167 */
168 @Test
169 public void testStatisticsMBeanUpdatesAsStatsChange() throws Exception {
170 ManagementService.registerMBeans(manager, mBeanServer, false, false, false, true, false);
171 Ehcache cache = manager.getCache("sampleCache1");
172 ObjectName name = CacheStatistics.createObjectName(manager.getName(), cache.getName());
173 assertEquals(Long.valueOf(0), mBeanServer.getAttribute(name, "ObjectCount"));
174 cache.put(new Element("1", "value"));
175 cache.get("1");
176 Thread.sleep(20);
177 assertEquals(Long.valueOf(1), mBeanServer.getAttribute(name, "ObjectCount"));
178 assertEquals(Long.valueOf(1), mBeanServer.getAttribute(name, "MemoryStoreObjectCount"));
179 assertEquals(Long.valueOf(1), mBeanServer.getAttribute(name, "DiskStoreObjectCount"));
180
181
182
183
184 }
185
186 /***
187 * Integration test for the registration service
188 */
189 @Test
190 public void testRegistrationServiceThreeTrue() throws Exception {
191 ManagementService.registerMBeans(manager, mBeanServer, true, true, true, false, false);
192 assertEquals(31, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
193
194 }
195
196 /***
197 * Integration test for the registration service
198 */
199 @Test
200 public void testRegistrationServiceTwoTrue() throws Exception {
201 ManagementService.registerMBeans(manager, mBeanServer, true, true, false, false, false);
202 assertEquals(16, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
203
204 }
205
206 /***
207 * Integration test for the registration service
208 */
209 @Test
210 public void testRegistrationServiceOneTrue() throws Exception {
211 ManagementService.registerMBeans(manager, mBeanServer, true, false, false, false, false);
212 assertEquals(1, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
213
214 }
215
216 /***
217 * Integration test for the registration service
218 */
219 @Test
220 public void testRegistrationServiceNoneTrue() throws Exception {
221 ManagementService.registerMBeans(manager, mBeanServer, false, false, false, false, false);
222 assertEquals(0, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
223
224 }
225
226 /***
227 * Can we register the CacheManager MBean?
228 */
229 @Test
230 public void testRegisterCacheManager() throws Exception {
231
232 Ehcache ehcache = new net.sf.ehcache.Cache("testNoOverflowToDisk", 1, false, false, 500, 200);
233 manager.addCache(ehcache);
234
235 ehcache.put(new Element("key1", "value1"));
236 ehcache.put(new Element("key2", "value1"));
237 assertNull(ehcache.get("key1"));
238 assertNotNull(ehcache.get("key2"));
239
240
241 ObjectName name = new ObjectName("net.sf.ehcache:type=CacheManager,name=1");
242 CacheManager cacheManager = new CacheManager(manager);
243 mBeanServer.registerMBean(cacheManager, name);
244 mBeanServer.unregisterMBean(name);
245
246 name = new ObjectName("net.sf.ehcache:type=CacheManager.Cache,CacheManager=1,name=testOverflowToDisk");
247 mBeanServer.registerMBean(new Cache(ehcache), name);
248 mBeanServer.unregisterMBean(name);
249
250 name = new ObjectName("net.sf.ehcache:type=CacheManager.Cache,CacheManager=1,name=sampleCache1");
251 mBeanServer.registerMBean(new Cache(manager.getCache("sampleCache1")), name);
252 mBeanServer.unregisterMBean(name);
253
254 }
255
256
257 /***
258 * Can we register the CacheManager MBean?
259 */
260 @Test
261 public void testListCachesFromManager() throws Exception {
262 ManagementService.registerMBeans(manager, mBeanServer, true, false, false, false, false);
263
264 Ehcache ehcache = manager.getCache("sampleCache1");
265
266 ehcache.put(new Element("key1", "value1"));
267 ehcache.put(new Element("key2", "value1"));
268 assertNotNull(ehcache.get("key1"));
269 assertNotNull(ehcache.get("key2"));
270
271 ObjectName name = CacheManager.createObjectName(manager);
272
273 Object object = mBeanServer.getAttribute(name, "Status");
274 LOG.info(object.toString());
275
276 List caches = (List) mBeanServer.getAttribute(name, "Caches");
277 assertEquals(15, caches.size());
278
279 for (int i = 0; i < caches.size(); i++) {
280 Cache cache = (Cache) caches.get(i);
281 String cacheName = cache.getName();
282 CacheStatistics cacheStatistics = cache.getStatistics();
283 CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
284 LOG.info(cacheName + " " + cacheStatistics + " " + cacheConfiguration);
285 }
286 }
287
288 /***
289 * Shows that all MBeans are fully traversable locally
290 *
291 * @throws JMException
292 */
293 @Test
294 public void testTraversalUsingMBeanServer() throws JMException {
295
296
297 traverseMBeanAttributesUsingMBeanServer("CacheManager");
298
299
300
301 traverseMBeanAttributesUsingMBeanServer("Cache");
302
303
304 traverseMBeanAttributesUsingMBeanServer("CacheStatistics");
305
306
307 traverseMBeanAttributesUsingMBeanServer("CacheConfiguration");
308
309 }
310
311
312 /***
313 * Creates an RMI JMXConnectorServer, connects to it and demonstrates what attributes are traversable.
314 * The answer is not all.
315 * <p/>
316 * Note that this test creates a Registry which will keep running until the JVM Exists. There
317 * is no way to stop it but it should do no harm.
318 */
319 @Test
320 public void testJMXConnectorServer() throws Exception {
321
322 ManagementService.registerMBeans(manager, mBeanServer, true, true, true, true, true);
323
324 LocateRegistry.createRegistry(55000);
325 String serverUrl = "service:jmx:rmi:///jndi/rmi://localhost:55000/server";
326 JMXServiceURL url = new JMXServiceURL(serverUrl);
327 JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mBeanServer);
328 cs.start();
329 JMXConnector connector = cs.toJMXConnector(null);
330 connector.connect(null);
331 MBeanServerConnection connection = connector.getMBeanServerConnection();
332 assertEquals(OBJECTS_IN_TEST_EHCACHE, connection.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
333
334
335 Ehcache ehcache = manager.getCache("sampleCache1");
336
337 ehcache.put(new Element("key1", "value1"));
338 ehcache.put(new Element("key2", "value1"));
339 assertNotNull(ehcache.get("key1"));
340 assertNotNull(ehcache.get("key2"));
341
342
343
344
345
346
347
348
349
350
351 traverseMBeanAttributes(connection, "CacheStatistics");
352
353
354 traverseMBeanAttributes(connection, "CacheConfiguration");
355
356 cs.stop();
357 }
358
359 @Test
360 public void testSupportsDecoratedCaches() {
361 ManagementService.registerMBeans(manager, mBeanServer, true, true, true, true, true);
362
363 net.sf.ehcache.Cache cache = new net.sf.ehcache.Cache(new net.sf.ehcache.config.CacheConfiguration("decoratedCache", 1000));
364 BlockingCache blockingCache = new BlockingCache(cache);
365
366 manager.addCacheIfAbsent(blockingCache);
367 }
368
369 private void traverseMBeanAttributes(MBeanServerConnection connection, String type) throws JMException, IOException {
370 Set objectNames = connection.queryNames(new ObjectName("net.sf.ehcache:type=" + type + ",*"), null);
371 for (Iterator iterator = objectNames.iterator(); iterator.hasNext();) {
372 ObjectName objectName = (ObjectName) iterator.next();
373 MBeanInfo mBeanInfo = connection.getMBeanInfo(objectName);
374 MBeanAttributeInfo[] attributes = mBeanInfo.getAttributes();
375 for (MBeanAttributeInfo attribute : attributes) {
376 LOG.info(attribute.getName() + " " + connection.getAttribute(objectName, attribute.getName()));
377 }
378 }
379 }
380
381 private void traverseMBeanAttributesUsingMBeanServer(String type) throws JMException {
382 Set objectNames = mBeanServer.queryNames(new ObjectName("net.sf.ehcache:type=" + type + ",*"), null);
383 for (Iterator iterator = objectNames.iterator(); iterator.hasNext();) {
384 ObjectName objectName = (ObjectName) iterator.next();
385 MBeanInfo mBeanInfo = mBeanServer.getMBeanInfo(objectName);
386 MBeanAttributeInfo[] attributes = mBeanInfo.getAttributes();
387 for (MBeanAttributeInfo attribute : attributes) {
388 LOG.info(attribute.getName() + " " + mBeanServer.getAttribute(objectName, attribute.getName()));
389 }
390 }
391 }
392
393
394 }