View Javadoc

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          //Ensure the CacheManager shutdown clears all ObjectNames from the MBeanServer
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 //        Thread.sleep(1000000);
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 //        Thread.sleep(1000000);
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 //        Thread.sleep(1000000);
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         //Set size so the second element overflows to disk.
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         //Test CacheManager
296         //not all attributes are accessible due to serializability constraints
297         traverseMBeanAttributesUsingMBeanServer("CacheManager");
298 
299         //Test Cache
300         //not all attributes are accessible due to serializability constraints
301         traverseMBeanAttributesUsingMBeanServer("Cache");
302 
303         //Test CacheStatistics
304         traverseMBeanAttributesUsingMBeanServer("CacheStatistics");
305 
306         //Test CacheConfiguration
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         //Test CacheManager
343         //not all attributes are accessible due to serializability constraints
344         //traverseMBeanAttributes(connection, "CacheManager");
345 
346         //Test Cache
347         //not all attributes are accessible due to serializability constraints
348         //traverseMBeanAttributes(connection, "Cache");
349 
350         //Test CacheStatistics
351         traverseMBeanAttributes(connection, "CacheStatistics");
352 
353         //Test CacheConfiguration
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 }