KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > management > MXBean


1 /*
2  * @(#)MXBean.java 1.18 06/06/22
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.management;
9
10 import java.lang.annotation.Documented JavaDoc;
11 import java.lang.annotation.ElementType JavaDoc;
12 import java.lang.annotation.Retention JavaDoc;
13 import java.lang.annotation.RetentionPolicy JavaDoc;
14 import java.lang.annotation.Target JavaDoc;
15
16 // remaining imports are for Javadoc
17
import java.beans.ConstructorProperties JavaDoc;
18 import java.io.InvalidObjectException JavaDoc;
19 import java.lang.management.MemoryUsage JavaDoc;
20 import java.lang.reflect.UndeclaredThrowableException JavaDoc;
21 import java.util.Arrays JavaDoc;
22 import java.util.List JavaDoc;
23 import javax.management.openmbean.ArrayType JavaDoc;
24 import javax.management.openmbean.CompositeData JavaDoc;
25 import javax.management.openmbean.CompositeDataInvocationHandler JavaDoc;
26 import javax.management.openmbean.CompositeDataSupport JavaDoc;
27 import javax.management.openmbean.CompositeDataView JavaDoc;
28 import javax.management.openmbean.CompositeType JavaDoc;
29 import javax.management.openmbean.OpenDataException JavaDoc;
30 import javax.management.openmbean.OpenMBeanInfo JavaDoc;
31 import javax.management.openmbean.OpenType JavaDoc;
32 import javax.management.openmbean.SimpleType JavaDoc;
33 import javax.management.openmbean.TabularData JavaDoc;
34 import javax.management.openmbean.TabularDataSupport JavaDoc;
35 import javax.management.openmbean.TabularType JavaDoc;
36
37 /**
38     <p>Annotation to mark an interface explicitly as being an MXBean
39     interface, or as not being an MXBean interface. By default, an
40     interface is an MXBean interface if its name ends with {@code
41     MXBean}, as in {@code SomethingMXBean}. The following interfaces
42     are MXBean interfaces:</p>
43
44     <pre>
45     public interface WhatsitMXBean {}
46
47     &#64;MXBean
48     public interface Whatsit1Interface {}
49
50     &#64;MXBean(true)
51     public interface Whatsit2Interface {}
52     </pre>
53
54     <p>The following interfaces are not MXBean interfaces:</p>
55
56     <pre>
57     public interface Whatsit3Interface{}
58
59     &#64;MXBean(false)
60     public interface MisleadingMXBean {}
61     </pre>
62
63     <h3><a name="MXBean-spec">MXBean specification</a></h3>
64
65     <p>The MXBean concept provides a simple way to code an MBean
66       that only references a predefined set of types, the ones defined
67       by {@link javax.management.openmbean}. In this way, you can be
68       sure that your MBean will be usable by any client, including
69       remote clients, without any requirement that the client have
70       access to <em>model-specific classes</em> representing the types
71       of your MBeans.</p>
72
73     <p>The concepts are easier to understand by comparison with the
74       Standard MBean concept. Here is how a managed object might be
75       represented as a Standard MBean, and as an MXBean:</p>
76
77     <table border="1" cellpadding="5">
78       <tr>
79     <th>Standard MBean</th><th>MXBean</th>
80       </tr>
81       <tr>
82     <td><pre>
83 public interface MemoryPool<b>MBean</b> {
84     String getName();
85     MemoryUsage getUsage();
86     // ...
87 }
88       </pre></td>
89     <td><pre>
90 public interface MemoryPool<b>MXBean</b> {
91     String getName();
92     MemoryUsage getUsage();
93     // ...
94 }
95       </pre></td>
96       </tr>
97     </table>
98
99     <p>As you can see, the definitions are very similar. The only
100       difference is that the convention for naming the interface is to use
101       <code><em>Something</em>MXBean</code> for MXBeans, rather than
102       <code><em>Something</em>MBean</code> for Standard MBeans.</p>
103
104     <p>In this managed object, there is an attribute called
105       <code>Usage</code> of type {@link MemoryUsage}. The point of an
106       attribute like this is that it gives a coherent snapshot of a set
107       of data items. For example, it might include the current amount
108       of used memory in the memory pool, and the current maximum of the
109       memory pool. If these were separate items, obtained with separate
110       {@link MBeanServer#getAttribute getAttribute} calls, then we could
111       get values seen at different times that were not consistent. We
112       might get a <code>used</code> value that was greater than the
113       <code>max</code> value.</p>
114
115     <p>So, we might define <code>MemoryUsage</code> like this:</p>
116
117     <table border="1" cellpadding="5">
118       <tr>
119     <th>Standard MBean</th><th>MXBean</th>
120       </tr>
121       <tr>
122     <td><pre>
123 public class MemoryUsage <b>implements Serializable</b> {
124     // standard JavaBean conventions with getters
125
126     public MemoryUsage(long init, long used,
127                        long committed, long max) {...}
128     long getInit() {...}
129     long getUsed() {...}
130     long getCommitted() {...}
131     long getMax() {...}
132 }
133       </pre></td>
134     <td><pre>
135 public class MemoryUsage {
136     // standard JavaBean conventions with getters
137     <b>&#64;ConstructorProperties({"init", "used", "committed", "max"})</b>
138     public MemoryUsage(long init, long used,
139                        long committed, long max) {...}
140     long getInit() {...}
141     long getUsed() {...}
142     long getCommitted() {...}
143     long getMax() {...}
144 }
145       </pre></td>
146       </tr>
147     </table>
148
149     <p>The definitions are the same in the two cases, except
150       that with the MXBean, <code>MemoryUsage</code> no longer needs to
151       be marked <code>Serializable</code> (though it can be). On
152       the other hand, we have added a {@code @ConstructorProperties} annotation
153       to link the constructor parameters to the corresponding getters.
154       We will see more about this below.</p>
155
156     <p><code>MemoryUsage</code> is a <em>model-specific class</em>.
157       With Standard MBeans, a client of the MBean Server cannot access the
158       <code>Usage</code> attribute if it does not know the class
159       <code>MemoryUsage</code>. Suppose the client is a generic console
160       based on JMX technology. Then the console would have to be
161       configured with the model-specific classes of every application it
162       might connect to. The problem is even worse for clients that are
163       not written in the Java language. Then there may not be any way
164       to tell the client what a <code>MemoryUsage</code> looks like.</p>
165
166     <p>This is where MXBeans differ from Standard MBeans. Although we
167       define the management interface in almost exactly the same way,
168       the MXBean framework <em>converts</em> model-specific classes into
169       standard classes from the Java platform. Using arrays and the
170       {@link javax.management.openmbean.CompositeData CompositeData} and
171       {@link javax.management.openmbean.TabularData TabularData} classes
172       from the standard {@link javax.management.openmbean} package, it
173       is possible to build data structures of arbitrary complexity
174       using only standard classes.</p>
175
176     <p>This becomes clearer if we compare what the clients of the two
177       models might look like:</p>
178
179     <table border="1" cellpadding="5">
180       <tr>
181     <th>Standard MBean</th><th>MXBean</th>
182       </tr>
183       <tr>
184     <td><pre>
185 String name = (String)
186     mbeanServer.{@link MBeanServer#getAttribute
187     getAttribute}(objectName, "Name");
188 <b>MemoryUsage</b> usage = (<b>MemoryUsage</b>)
189     mbeanServer.getAttribute(objectName, "Usage");
190 <b>long used = usage.getUsed();</b>
191       </pre></td>
192     <td><pre>
193 String name = (String)
194     mbeanServer.{@link MBeanServer#getAttribute
195     getAttribute}(objectName, "Name");
196 <b>{@link CompositeData}</b> usage = (<b>CompositeData</b>)
197     mbeanServer.getAttribute(objectName, "Usage");
198 <b>long used = (Long) usage.{@link CompositeData#get get}("used");</b>
199       </pre></td>
200     </table>
201
202     <p>For attributes with simple types like <code>String</code>, the
203       code is the same. But for attributes with complex types, the
204       Standard MBean code requires the client to know the model-specific
205       class <code>MemoryUsage</code>, while the MXBean code requires no
206       non-standard classes.</p>
207
208     <p>The client code shown here is slightly more complicated for the
209       MXBean client. But, if the client does in fact know the model,
210       here the interface <code>MemoryPoolMXBean</code> and the
211       class <code>MemoryUsage</code>, then it can construct a
212       <em>proxy</em>. This is the recommended way to interact with
213       managed objects when you know the model beforehand, regardless
214       of whether you are using Standard MBeans or MXBeans:</p>
215
216     <table border="1" cellpadding="5">
217       <tr>
218     <th>Standard MBean</th><th>MXBean</th>
219       </tr>
220       <tr>
221     <td><pre>
222 MemoryPool<b>MBean</b> proxy =
223     JMX.<b>{@link JMX#newMBeanProxy(MBeanServerConnection, ObjectName,
224           Class) newMBeanProxy}</b>(
225         mbeanServer,
226         objectName,
227         MemoryPool<b>MBean</b>.class);
228 String name = proxy.getName();
229 MemoryUsage usage = proxy.getUsage();
230 long used = usage.getUsed();
231       </pre></td>
232     <td><pre>
233 MemoryPool<b>MXBean</b> proxy =
234     JMX.<b>{@link JMX#newMXBeanProxy(MBeanServerConnection, ObjectName,
235           Class) newMXBeanProxy}</b>(
236         mbeanServer,
237         objectName,
238         MemoryPool<b>MXBean</b>.class);
239 String name = proxy.getName();
240 MemoryUsage usage = proxy.getUsage();
241 long used = usage.getUsed();
242       </pre></td>
243       </tr>
244     </table>
245
246     <p>Implementing the MemoryPool object works similarly for both
247       Standard MBeans and MXBeans.</p>
248
249     <table border="1" cellpadding="5">
250       <tr>
251     <th>Standard MBean</th><th>MXBean</th>
252       </tr>
253       <tr>
254     <td><pre>
255 public class MemoryPool
256         implements MemoryPool<b>MBean</b> {
257     public String getName() {...}
258     public MemoryUsage getUsage() {...}
259     // ...
260 }
261       </pre></td>
262     <td><pre>
263 public class MemoryPool
264         implements MemoryPool<b>MXBean</b> {
265     public String getName() {...}
266     public MemoryUsage getUsage() {...}
267     // ...
268 }
269       </pre></td>
270       </tr>
271     </table>
272
273     <p>Registering the MBean in the MBean Server works in the same way
274       in both cases:</p>
275
276     <table border="1" cellpadding="5">
277       <tr>
278     <th>Standard MBean</th><th>MXBean</th>
279       </tr>
280       <tr>
281     <td><pre>
282 {
283     MemoryPool<b>MBean</b> pool = new MemoryPool();
284     mbeanServer.{@link MBeanServer#registerMBean
285     registerMBean}(pool, objectName);
286 }
287       </pre></td>
288     <td><pre>
289 {
290     MemoryPool<b>MXBean</b> pool = new MemoryPool();
291     mbeanServer.{@link MBeanServer#registerMBean
292     registerMBean}(pool, objectName);
293 }
294       </pre></td>
295       </tr>
296     </table>
297
298
299     <h2><a name="mxbean-def">Definition of an MXBean</a></h2>
300
301     <p>An MXBean is a kind of MBean. An MXBean object can be
302       registered directly in the MBean Server, or it can be used as an
303       argument to {@link StandardMBean} and the resultant MBean
304       registered in the MBean Server.</p>
305
306     <p>When an object is registered in the MBean Server using the
307       {@code registerMBean} or {@code createMBean} methods of the
308       {@link MBeanServer} interface, the object's class is examined
309       to determine what type of MBean it is:</p>
310
311     <ul>
312       <li>If the class implements the interface {@link DynamicMBean}
313     then the MBean is a Dynamic MBean. Note that the class
314         {@code StandardMBean} implements this interface, so this
315         case applies to a Standard MBean or MXBean created using
316         the class {@code StandardMBean}.</li>
317
318       <li>Otherwise, if the class matches the Standard MBean naming
319     conventions, then the MBean is a Standard MBean.</li>
320
321       <li>Otherwise, it may be an MXBean. The set of interfaces
322     implemented by the object is examined for interfaces that:
323
324     <ul>
325       <li>have a class name <code><em>S</em>MXBean</code> where
326         <code><em>S</em></code> is any non-empty string, and
327         do not have an annotation {@code @MXBean(false)}; and/or</li>
328       <li>have an annotation {@code @MXBean(true)}
329         or just {@code @MXBean}.</li>
330     </ul>
331
332     If there is exactly one such interface, or if there is one
333     such interface that is a subinterface of all the others, then
334     the object is an MXBean. The interface in question is the
335     <em>MXBean interface</em>. In the example above, the MXBean
336     interface is {@code MemoryPoolMXBean}.
337
338       <li>If none of these conditions is met, the MBean is invalid and
339     the attempt to register it will generate {@link
340     NotCompliantMBeanException}.
341     </ul>
342
343     <p>Every Java type that appears as the parameter or return type of a
344       method in an MXBean interface must be <em>convertible</em> using
345       the rules below. Additionally, parameters must be
346       <em>reconstructible</em> as defined below.</p>
347
348     <p>An attempt to construct an MXBean that does not conform to the
349       above rules will produce an exception.</p>
350
351
352     <h2><a name="naming-conv">Naming conventions</a></h2>
353
354     <p>The same naming conventions are applied to the methods in an
355       MXBean as in a Standard MBean:</p>
356
357     <ol>
358       <li>A method <code><em>T</em> get<em>N</em>()</code>, where
359     <code><em>T</em></code> is a Java type (not <code>void</code>)
360     and <code><em>N</em></code> is a non-empty string, specifies
361     that there is a readable attribute called
362     <code><em>N</em></code>. The Java type and Open type of the
363     attribute are determined by the mapping rules below.
364     The method {@code final Class getClass()} inherited from {@code
365     Object} is ignored when looking for getters.</li>
366
367       <li>A method <code>boolean is<em>N</em>()</code> specifies that
368     there is a readable attribute called <code><em>N</em></code>
369     with Java type <code>boolean</code> and Open type
370     <code>SimpleType.Boolean</code>.</li>
371
372       <li>A method <code>void set<em>N</em>(<em>T</em> x)</code>
373     specifies that there is a writeable attribute called
374     <code><em>N</em></code>. The Java type and Open type of the
375     attribute are determined by the mapping rules below. (Of
376     course, the name <code>x</code> of the parameter is
377     irrelevant.)</li>
378
379       <li>Every other method specifies that there is an operation with
380     the same name as the method. The Java type and Open type of the
381     return value and of each parameter are determined by the mapping
382     rules below.</li>
383     </ol>
384
385     <p>The rules for <code>get<em>N</em></code> and
386       <code>is<em>N</em></code> collectively define the notion of a
387       <em>getter</em>. The rule for <code>set<em>N</em></code> defines
388       the notion of a <em>setter</em>.</p>
389
390     <p>It is an error for there to be two getters with the same name, or
391       two setters with the same name. If there is a getter and a setter
392       for the same name, then the type <code><em>T</em></code> in both
393       must be the same. In this case the attribute is read/write. If
394       there is only a getter or only a setter, the attribute is
395       read-only or write-only respectively.</p>
396
397
398     <h2><a name="mapping-rules">Type mapping rules</a></h2>
399
400     <p>An MXBean is a kind of Open MBean, as defined by the {@link
401       javax.management.openmbean} package. This means that the types of
402       attributes, operation parameters, and operation return values must
403       all be describable using <em>Open Types</em>, that is the four
404       standard subclasses of {@link javax.management.openmbean.OpenType}.
405       MXBeans achieve this by mapping Java types into Open Types.</p>
406
407     <p>For every Java type <em>J</em>, the MXBean mapping is described
408       by the following information:</p>
409
410     <ul>
411       <li>The corresponding Open Type, <em>opentype(J)</em>. This is
412     an instance of a subclass of {@link
413     javax.management.openmbean.OpenType}.</li>
414       <li>The <em>mapped</em> Java type, <em>opendata(J)</em>, which is
415     always the same for any given <em>opentype(J)</em>. This is a Java
416     class.</li>
417       <li>How a value is converted from type <em>J</em> to type
418     <em>opendata(J)</em>.</li>
419       <li>How a value is converted from type <em>opendata(J)</em> to
420     type <em>J</em>, if it can be.</li>
421     </ul>
422
423     <p>For example, for the Java type {@code List<String>}:</p>
424
425     <ul>
426       <li>The Open Type, <em>opentype(</em>{@code
427     List<String>}<em>)</em>, is {@link ArrayType}<code>(1, </code>{@link
428       SimpleType#STRING}<code>)</code>, representing a 1-dimensional
429       array of <code>String</code>s.</li>
430       <li>The mapped Java type, <em>opendata(</em>{@code
431     List<String>}<em>)</em>, is {@code String[]}.</li>
432       <li>A {@code List<String>} can be converted to a {@code String[]}
433       using {@link List#toArray(Object[]) List.toArray(new
434       String[0])}.</li>
435       <li>A {@code String[]} can be converted to a {@code List<String>}
436       using {@link Arrays#asList Arrays.asList}.</li>
437     </ul>
438
439     <p>If no mapping rules exist to derive <em>opentype(J)</em> from
440       <em>J</em>, then <em>J</em> cannot be the type of a method
441       parameter or return value in an MXBean interface.</p>
442
443     <p>If there is a way to convert <em>opendata(J)</em> back to
444       <em>J</em> then we say that <em>J</em> is
445       <em>reconstructible</em>. All method parameters in an MXBean
446       interface must be reconstructible, because when the MXBean
447       framework is invoking a method it will need to convert those
448       parameters from <em>opendata(J)</em> to <em>J</em>. In a proxy
449       generated by {@link JMX#newMXBeanProxy(MBeanServerConnection,
450       ObjectName, Class) JMX.newMXBeanProxy}, it is the return values
451       of the methods in the MXBean interface that must be
452       reconstructible.</p>
453
454     <p>Null values are allowed for all Java types and Open Types,
455       except primitive Java types where they are not possible. When
456       converting from type <em>J</em> to type <em>opendata(J)</em> or
457       from type <em>opendata(J)</em> to type <em>J</em>, a null value is
458       mapped to a null value.</p>
459
460     <p>The following table summarizes the type mapping rules.</p>
461
462     <table border="1" cellpadding="5">
463       <tr>
464     <th>Java type <em>J</em></th>
465     <th><em>opentype(J)</em></th>
466     <th><em>opendata(J)</em></th>
467       </tr>
468       <tbody cellvalign="top">
469     <tr>
470       <td>{@code int}, {@code boolean}, etc<br>
471         (the 8 primitive Java types)</td>
472       <td>{@code SimpleType.INTEGER},<br>
473         {@code SimpleType.BOOLEAN}, etc</td>
474       <td>{@code Integer}, {@code Boolean}, etc<br>
475         (the corresponding boxed types)</td>
476     </tr>
477     <tr>
478       <td>{@code Integer}, {@code ObjectName}, etc<br>
479         (the types covered by {@link SimpleType})</td>
480       <td>the corresponding {@code SimpleType}</td>
481       <td><em>J</em>, the same type</td>
482     </tr>
483     <tr>
484       <td>{@code int[]} etc<br>
485         (a one-dimensional array with<br>
486         primitive element type)</td>
487       <td>{@code ArrayType.getPrimitiveArrayType(int[].class)} etc</td>
488       <td><em>J</em>, the same type</td>
489     <tr>
490       <td><em>E</em>{@code []}<br>
491         (an array with non-primitive element type <em>E</em>;
492           this includes {@code int[][]}, where <em>E</em> is {@code int[]})</td>
493       <td>{@code ArrayType.getArrayType(}<em>opentype(E)</em>{@code )}</td>
494       <td><em>opendata(E)</em>{@code []}</td>
495     </tr>
496     <tr>
497       <td>{@code List<}<em>E</em>{@code >}<br>
498         {@code Set<}<em>E</em>{@code >}<br>
499         {@code SortedSet<}<em>E</em>{@code >} (see below)</td>
500       <td>same as for <em>E</em>{@code []}</td>
501       <td>same as for <em>E</em>{@code []}</td>
502     </tr>
503     <tr>
504       <td>An enumeration <em>E</em><br>
505         (declared in Java as {@code enum }<em>E</em>
506         {@code {...}})</td>
507       <td>{@code SimpleType.STRING}</td>
508       <td>{@code String}</td>
509     </tr>
510     <tr>
511       <td>{@code Map<}<em>K</em>,<em>V</em>{@code >}<br>
512         {@code SortedMap<}<em>K</em>,<em>V</em>{@code >}</td>
513       <td>{@link TabularType}<br>
514         (see below)</td>
515       <td>{@link TabularData}<br>
516         (see below)</td>
517     </tr>
518     <tr>
519       <td>An MXBean interface</td>
520       <td>{@code SimpleType.OBJECTNAME}<br>
521         (see below)</td>
522       <td>{@link ObjectName}<br>
523         (see below)</td>
524     </tr>
525     <tr>
526       <td>Any other type</td>
527       <td>{@link CompositeType},
528         if possible<br>
529         (see below)</td>
530       <td>{@link CompositeData}</td>
531       </tbody>
532     </table>
533
534     <p>The following sections give further details of these rules.</p>
535
536
537     <h3>Mappings for primitive types</h3>
538
539     <p>The 8 primitive Java types
540       ({@code boolean}, {@code byte}, {@code short}, {@code int}, {@code
541       long}, {@code float}, {@code double}, {@code char}) are mapped to the
542       corresponding boxed types from {@code java.lang}, namely {@code
543       Boolean}, {@code Byte}, etc. The Open Type is the corresponding
544       {@code SimpleType}. Thus, <em>opentype(</em>{@code
545       long}<em>)</em> is {@code SimpleType.LONG}, and
546       <em>opendata(</em>{@code long}<em>)</em> is {@code
547       java.lang.Long}.</p>
548
549     <p>An array of primitive type such as {@code long[]} can be represented
550       directly as an Open Type. Thus, <em>openType(</em>{@code
551       long[]}<em>)</em> is {@code
552       ArrayType.getPrimitiveArrayType(long[].class)}, and
553       <em>opendata(</em>{@code long[]}<em>)</em> is {@code
554       long[]}.</p>
555
556     <p>In practice, the difference between a plain {@code int} and {@code
557       Integer}, etc, does not show up because operations in the JMX API
558       are always on Java objects, not primitives. However, the
559       difference <em>does</em> show up with arrays.</p>
560
561
562     <h3>Mappings for collections ({@code List<}<em>E</em>{@code >} etc)</h3>
563
564     <p>A {@code List<}<em>E</em>{@code >} or {@code
565       Set<}<em>E</em>{@code >}, such as {@code List<String>} or {@code
566     Set<ObjectName>}, is mapped in the same way as an array of the
567       same element type, such as {@code String[]} or {@code
568       ObjectName[]}.</p>
569
570     <p>A {@code SortedSet<}<em>E</em>{@code >} is also mapped in the
571       same way as an <em>E</em>{@code []}, but it is only convertible if
572       <em>E</em> is a class or interface that implements {@link
573       java.lang.Comparable}. Thus, a {@code SortedSet<String>} or
574     {@code SortedSet<Integer>} is convertible, but a {@code
575       SortedSet<int[]>} or {@code SortedSet<List<String>>} is not. The
576         conversion of a {@code SortedSet} instance will fail with an
577         {@code IllegalArgumentException} if it has a
578         non-null {@link java.util.SortedSet#comparator()
579         comparator()}.</p>
580
581     <p>A {@code List<}<em>E</em>{@code >} is reconstructed as a
582       {@code java.util.ArrayList<}<em>E</em>{@code >};
583       a {@code Set<}<em>E</em>{@code >} as a
584       {@code java.util.HashSet<}<em>E</em>{@code >};
585       a {@code SortedSet<}<em>E</em>{@code >} as a
586       {@code java.util.TreeSet<}<em>E</em>{@code >}.</p>
587
588
589     <h3>Mappings for maps ({@code Map<}<em>K</em>,<em>V</em>{@code >} etc)</h3>
590
591     <p>A {@code Map<}<em>K</em>,<em>V</em>{@code >} or {@code
592       SortedMap<}<em>K</em>,<em>V</em>{@code >}, for example {@code
593       Map<String,ObjectName>}, has Open Type {@link TabularType} and is mapped
594     to a {@link TabularData}.
595     The {@code TabularType} has two items called {@code key} and
596     {@code value}. The Open Type of {@code key} is
597     <em>opentype(K)</em>, and the Open Type of {@code value} is
598     <em>opentype(V)</em>. The index of the {@code TabularType} is the
599     single item {@code key}.</p>
600
601     <p>For example, the {@code TabularType} for a {@code
602       Map<String,ObjectName>} might be constructed with code like
603     this:</p>
604
605     <pre>
606 String typeName =
607     "java.util.Map&lt;java.lang.String, javax.management.ObjectName&gt;";
608 String[] keyValue =
609     new String[] {"key", "value"};
610 OpenType[] openTypes =
611     new OpenType[] {SimpleType.STRING, SimpleType.OBJECTNAME};
612 CompositeType rowType =
613     new CompositeType(typeName, typeName, keyValue, keyValue, openTypes);
614 TabularType tabularType =
615     new TabularType(typeName, typeName, rowType, new String[] {"key"});
616     </pre>
617
618     <p>The {@code typeName} here is determined by the <a HREF="#type-names">
619       type name rules</a> detailed below.
620
621     <p>A {@code SortedMap<}<em>K</em>,<em>V</em>{@code >} is mapped in the
622       same way, but it is only convertible if
623       <em>K</em> is a class or interface that implements {@link
624       java.lang.Comparable}. Thus, a {@code SortedMap<String,int[]>}
625     is convertible, but a
626     {@code SortedMap<int[],String>} is not. The conversion of a
627       {@code SortedMap} instance will fail with an {@code
628       IllegalArgumentException} if it has a non-null {@link
629       java.util.SortedMap#comparator() comparator()}.</p>
630
631     <p>A {@code Map<}<em>K</em>,<em>V</em>{@code >} is reconstructed as
632       a {@code java.util.HashMap<}<em>K</em>,<em>V</em>{@code >};
633       a {@code SortedMap<}<em>K</em>,<em>V</em>{@code >} as
634       a {@code java.util.TreeMap<}<em>K</em>,<em>V</em>{@code >}.</p>
635
636     <p>{@code TabularData} is an interface. The concrete class that is
637       used to represent a {@code Map<}<em>K</em>,<em>V</em>{@code >} as
638       Open Data is {@link TabularDataSupport},
639       or another class implementing {@code
640       TabularData} that serializes as {@code TabularDataSupport}.</p>
641
642
643     <h3><a name="mxbean-map">Mappings for MXBean interfaces</a></h3>
644
645     <p>An MXBean interface, or a type referenced within an MXBean
646       interface, can reference another MXBean interface, <em>J</em>.
647       Then <em>opentype(J)</em> is {@code SimpleType.OBJECTNAME} and
648       <em>opendata(J)</em> is {@code ObjectName}.</p>
649
650     <p>For example, suppose you have two MXBean interfaces like this:</p>
651
652     <pre>
653 public interface ProductMXBean {
654     public ModuleMXBean[] getModules();
655 }
656
657 public interface ModuleMXBean {
658     public ProductMXBean getProduct();
659 }
660     </pre>
661
662     <p>The object implementing the {@code ModuleMXBean} interface
663       returns from its {@code getProduct} method an object
664       implementing the {@code ProductMXBean} interface. The
665       {@code ModuleMXBean} object and the returned {@code
666       ProductMXBean} objects must both be registered as MXBeans in the
667       same MBean Server.</p>
668
669     <p>The method {@code ModuleMXBean.getProduct()} defines an
670       attribute called {@code Product}. The Open Type for this
671       attribute is {@code SimpleType.OBJECTNAME}, and the corresponding
672       {@code ObjectName} value will be the name under which the
673       referenced {@code ProductMXBean} is registered in the MBean
674       Server.</p>
675
676     <p>If you make an MXBean proxy for a {@code ModuleMXBean} and
677       call its {@code getProduct()} method, the proxy will map the
678       {@code ObjectName} back into a {@code ProductMXBean} by making
679       another MXBean proxy. More formally, when a proxy made with
680       {@link JMX#newMXBeanProxy(MBeanServerConnection, ObjectName,
681        Class)
682       JMX.newMXBeanProxy(mbeanServerConnection, objectNameX,
683       interfaceX)} needs to map {@code objectNameY} back into {@code
684       interfaceY}, another MXBean interface, it does so with {@code
685       JMX.newMXBeanProxy(mbeanServerConnection, objectNameY,
686       interfaceY)}. The implementation may return a proxy that was
687       previously created by a call to {@code JMX.newMXBeanProxy}
688       with the same parameters, or it may create a new proxy.</p>
689
690     <p>The reverse mapping is illustrated by the following change to the
691       {@code ModuleMXBean} interface:</p>
692
693     <pre>
694 public interface ModuleMXBean {
695     public ProductMXBean getProduct();
696     public void setProduct(ProductMXBean c);
697 }
698     </pre>
699
700     <p>The presence of the {@code setProduct} method now means that the
701       {@code Product} attribute is read/write. As before, the value
702       of this attribute is an {@code ObjectName}. When the attribute is
703       set, the {@code ObjectName} must be converted into the
704       {@code ProductMXBean} object that the {@code setProduct} method
705       expects. This object will be an MXBean proxy for the given
706       {@code ObjectName} in the same MBean Server.</p>
707
708     <p>If you make an MXBean proxy for a {@code ModuleMXBean} and
709       call its {@code setProduct} method, the proxy will map its
710       {@code ProductMXBean} argument back into an {@code ObjectName}.
711       This will only work if the argument is in fact another proxy,
712       for a {@code ProductMXBean} in the same {@code
713       MBeanServerConnection}. The proxy can have been returned from
714       another proxy (like {@code ModuleMXBean.getProduct()} which
715       returns a proxy for a {@code ProductMXBean}); or it can have
716       been created by {@link
717       JMX#newMXBeanProxy(MBeanServerConnection, ObjectName, Class)
718       JMX.newMXBeanProxy}; or it can have been created using {@link
719       java.lang.reflect.Proxy Proxy} with an invocation handler that
720       is {@link MBeanServerInvocationHandler} or a subclass.</p>
721
722     <p>If the same MXBean were registered under two different
723       {@code ObjectName}s, a reference to that MXBean from another
724       MXBean would be ambiguous. Therefore, if an MXBean object is
725       already registered in an MBean Server and an attempt is made to
726       register it in the same MBean Server under another name, the
727       result is an {@link InstanceAlreadyExistsException}. Registering
728       the same MBean object under more than one name is discouraged in
729       general, notably because it does not work well for MBeans that are
730       {@link NotificationBroadcaster}s.</p>
731
732     <h3><a name="composite-map">Mappings for other types</a></h3>
733
734     <p>Given a Java class or interface <em>J</em> that does not match the other
735       rules in the table above, the MXBean framework will attempt to map
736       it to a {@link CompositeType} as follows. The type name of this
737       {@code CompositeType} is determined by the <a HREF="#type-names">
738       type name rules</a> below.</p>
739
740     <p>The class is examined for getters using the conventions
741       <a HREF="#naming-conv">above</a>. (Getters must be public
742       instance methods.) If there are no getters, or if
743       any getter has a type that is not convertible, then <em>J</em> is
744       not convertible.</p>
745
746     <p>If there is at least one getter and every getter has a
747       convertible type, then <em>opentype(J)</em> is a {@code
748       CompositeType} with one item for every getter. If the getter is
749
750     <blockquote>
751       <code><em>T</em> get<em>Name</em>()</code>
752     </blockquote>
753
754     then the item in the {@code CompositeType} is called {@code name}
755     and has type <em>opentype(T)</em>. For example, if the item is
756
757     <blockquote>
758       <code>String getOwner()</code>
759     </blockquote>
760
761     then the item is called {@code owner} and has Open Type {@code
762     SimpleType.STRING}. If the getter is
763
764     <blockquote>
765       <code>boolean is<em>Name</em>()</code>
766     </blockquote>
767
768     then the item in the {@code CompositeType} is called {@code name}
769     and has type {@code SimpleType.BOOLEAN}.</p>
770
771     <p>Notice that the first character (or code point) is converted to
772       lower case. This follows the Java Beans convention, which for
773       historical reasons is different from the Standard MBean
774       convention. In a Standard MBean or MXBean interface, a method
775       {@code getOwner} defines an attribute called {@code Owner}, while
776       in a Java Bean or mapped {@code CompositeType}, a method {@code
777       getOwner} defines a property or item called {@code owner}.</p>
778
779     <p>If two methods produce the same item name (for example, {@code
780       getOwner} and {@code isOwner}, or {@code getOwner} and {@code
781       getowner}) then the type is not convertible.</p>
782
783     <p>When the Open Type is {@code CompositeType}, the corresponding
784       mapped Java type (<em>opendata(J)</em>) is {@link
785       CompositeData}. The mapping from an instance of <em>J</em> to a
786       {@code CompositeData} corresponding to the {@code CompositeType}
787       just described is done as follows. First, if <em>J</em>
788       implements the interface {@link CompositeDataView}, then that
789       interface's {@link CompositeDataView#toCompositeData
790       toCompositeData} method is called to do the conversion.
791       Otherwise, the {@code CompositeData} is constructed by calling
792       the getter for each item and converting it to the corresponding
793       Open Data type. Thus, a getter such as</p>
794
795     <blockquote>
796       {@code List<String> getNames()}
797     </blockquote>
798
799     <p>will have been mapped to an item with name "{@code names}" and
800       Open Type {@code ArrayType(1, SimpleType.STRING)}. The conversion
801       to {@code CompositeData} will call {@code getNames()} and convert
802       the resultant {@code List<String>} into a {@code String[]} for the
803     item "{@code names}".</p>
804
805     <p>{@code CompositeData} is an interface. The concrete class that is
806       used to represent a type as Open Data is {@link
807       CompositeDataSupport}, or another class implementing {@code
808       CompositeData} that serializes as {@code
809       CompositeDataSupport}.</p>
810
811
812     <h4>Reconstructing an instance of Java type <em>J</em> from
813       a {@code CompositeData}</h4>
814
815     <p>If <em>opendata(J)</em> is {@code CompositeData} for a Java type
816       <em>J</em>, then either an instance of <em>J</em> can be
817       reconstructed from a {@code CompositeData}, or <em>J</em> is not
818       reconstructible. If any item in the {@code CompositeData} is not
819       reconstructible, then <em>J</em> is not reconstructible either.</p>
820
821     <p>For any given <em>J</em>, the following rules are consulted to
822       determine how to reconstruct instances of <em>J</em> from
823       {@code CompositeData}. The first applicable rule in the list is
824       the one that will be used.</p>
825
826     <ol>
827
828       <li><p>If <em>J</em> has a method<br>
829     {@code public static }<em>J </em>{@code from(CompositeData cd)}<br>
830     then that method is called to reconstruct an instance of
831     <em>J</em>.</p></li>
832
833       <li><p>Otherwise, if <em>J</em> has at least one public
834     constructor with a {@link ConstructorProperties} annotation, then one
835     of those constructors (not necessarily always the same one)
836     will be called to reconstruct an instance of <em>J</em>.
837     Every such annotation must list as many strings as the
838     constructor has parameters; each string must name a property
839     corresponding to a getter of <em>J</em>; and the type of this
840     getter must be the same as the corresponding constructor
841     parameter. It is not an error for there to be getters that
842     are not mentioned in the {@code ConstructorProperties} annotation
843     (these may correspond to information that is not needed to
844     reconstruct the object).</p>
845
846     <p>An instance of <em>J</em> is reconstructed by calling a
847     constructor with the appropriate reconstructed items from the
848     {@code CompositeData}. The constructor to be called will be
849     determined at runtime based on the items actually present in
850     the {@code CompositeData}, given that this {@code
851     CompositeData} might come from an earlier version of
852     <em>J</em> where not all the items were present. A
853     constructor is <em>applicable</em> if all the properties named
854     in its {@code ConstructorProperties} annotation are present as items
855     in the {@code CompositeData}. If no constructor is
856     applicable, then the attempt to reconstruct <em>J</em> fails.</p>
857
858     <p>For any possible combination of properties, it must be the
859     case that either (a) there are no applicable constructors, or
860     (b) there is exactly one applicable constructor, or (c) one of
861     the applicable constructors names a proper superset of the
862     properties named by each other applicable constructor. (In
863     other words, there should never be ambiguity over which
864     constructor to choose.) If this condition is not true, then
865     <em>J</em> is not reconstructible.</p></li>
866
867       <li><p>Otherwise, if <em>J</em> has a public no-arg constructor, and
868     for every getter in <em>J</em> with type
869     <em>T</em> and name <em>N</em> there is a corresponding setter
870     with the same name and type, then an instance of <em>J</em> is
871     constructed with the no-arg constructor and the setters are
872     called with the reconstructed items from the {@code CompositeData}
873     to restore the values. For example, if there is a method<br>
874     {@code public List<String> getNames()}<br>
875       then there must also be a method<br>
876       {@code public void setNames(List<String> names)}<br>
877         for this rule to apply.</p>
878
879         <p>If the {@code CompositeData} came from an earlier version of
880     <em>J</em>, some items might not be present. In this case,
881     the corresponding setters will not be called.</p></li>
882
883       <li><p>Otherwise, if <em>J</em> is an interface that has no methods
884     other than getters, an instance of <em>J</em> is constructed
885     using a {@link java.lang.reflect.Proxy} with a {@link
886     CompositeDataInvocationHandler} backed by the {@code
887     CompositeData} being converted.</p></li>
888
889       <li><p>Otherwise, <em>J</em> is not reconstructible.</p></li>
890     </ol>
891
892     <p>Here are examples showing different ways to code a type {@code
893       NamedNumber} that consists of an {@code int} and a {@code
894       String}. In each case, the {@code CompositeType} looks like this:</p>
895
896     <blockquote>
897       <pre>
898 {@link CompositeType}(
899     "NamedNumber", // typeName
900     "NamedNumber", // description
901     new String[] {"number", "name"}, // itemNames
902     new String[] {"number", "name"}, // itemDescriptions
903     new OpenType[] {SimpleType.INTEGER,
904                     SimpleType.STRING} // itemTypes
905 );
906       </pre>
907     </blockquote>
908
909     <ol>
910       <li>Static {@code from} method:
911
912     <blockquote>
913       <pre>
914 public class NamedNumber {
915     public int getNumber() {return number;}
916     public String getName() {return name;}
917     private NamedNumber(int number, String name) {
918         this.number = number;
919         this.name = name;
920     }
921     <b>public static NamedNumber from(CompositeData cd)</b> {
922         return new NamedNumber((Integer) cd.get("number"),
923                                (String) cd.get("name"));
924     }
925     private final int number;
926     private final String name;
927 }
928       </pre>
929     </blockquote>
930       </li>
931
932       <li>Public constructor with <code>&#64;ConstructorProperties</code> annotation:
933
934     <blockquote>
935       <pre>
936 public class NamedNumber {
937     public int getNumber() {return number;}
938     public String getName() {return name;}
939     <b>&#64;ConstructorProperties({"number", "name"})
940     public NamedNumber(int number, String name)</b> {
941         this.number = number;
942         this.name = name;
943     }
944     private final int number;
945     private final String name;
946 }
947       </pre>
948     </blockquote>
949       </li>
950
951       <li>Setter for every getter:
952
953     <blockquote>
954       <pre>
955 public class NamedNumber {
956     public int getNumber() {return number;}
957     public void <b>setNumber</b>(int number) {this.number = number;}
958     public String getName() {return name;}
959     public void <b>setName</b>(String name) {this.name = name;}
960     <b>public NamedNumber()</b> {}
961     private int number;
962     private String name;
963 }
964       </pre>
965     </blockquote>
966       </li>
967
968       <li>Interface with only getters:
969
970     <blockquote>
971       <pre>
972 public interface NamedNumber {
973     public int getNumber();
974     public String getName();
975 }
976       </pre>
977     </blockquote>
978       </li>
979     </ol>
980
981     <p>It is usually better for classes that simply represent a
982       collection of data to be <em>immutable</em>. An instance of an
983       immutable class cannot be changed after it has been constructed.
984       Notice that {@code CompositeData} itself is immutable.
985       Immutability has many advantages, notably with regard to
986       thread-safety and security. So the approach using setters should
987       generally be avoided if possible.</p>
988
989
990     <h3>Recursive types</h3>
991
992     <p>Recursive (self-referential) types cannot be used in MXBean
993       interfaces. This is a consequence of the immutability of {@link
994       CompositeType}. For example, the following type could not be the
995       type of an attribute, because it refers to itself:</p>
996
997     <pre>
998 public interface <b>Node</b> {
999     public String getName();
1000    public int getPriority();
1001    public <b>Node</b> getNext();
1002}
1003</pre>
1004
1005    <p>It is always possible to rewrite recursive types like this so
1006      they are no longer recursive. Doing so may require introducing
1007      new types. For example:</p>
1008
1009    <pre>
1010public interface <b>NodeList</b> {
1011    public List&lt;Node&gt; getNodes();
1012}
1013
1014public interface Node {
1015    public String getName();
1016    public int getPriority();
1017}
1018</pre>
1019
1020    <h3>MBeanInfo contents for an MXBean</h3>
1021
1022    <p>An MXBean is a type of Open MBean. However, for compatibility
1023      reasons, its {@link MBeanInfo} is not an {@link OpenMBeanInfo}.
1024      In particular, when the type of an attribute, parameter, or
1025      operation return value is a primitive type such as {@code int},
1026      or is {@code void} (for a return type), then the attribute,
1027      parameter, or operation will be represented respectively by an
1028      {@link MBeanAttributeInfo}, {@link MBeanParameterInfo}, or
1029      {@link MBeanOperationInfo} whose {@code getType()} or {@code
1030      getReturnType()} returns the primitive name ("{@code int}" etc).
1031      This is so even though the mapping rules above specify that the
1032      <em>opendata</em> mapping is the wrapped type ({@code Integer}
1033      etc).</p>
1034
1035    <p>The array of public constructors returned by {@link
1036      MBeanInfo#getConstructors()} for an MXBean that is directly
1037      registered in the MBean Server will contain all of the public
1038      constructors of that MXBean. If the class of the MXBean is not
1039      public then its constructors are not considered public either.
1040      The list returned for an MXBean that is constructed using the
1041      {@link StandardMBean} class is derived in the same way as for
1042      Standard MBeans. Regardless of how the MXBean was constructed,
1043      its constructor parameters are not subject to MXBean mapping
1044      rules and do not have a corresponding {@code OpenType}.</p>
1045
1046    <p>The array of notification types returned by {@link
1047      MBeanInfo#getNotifications()} for an MXBean that is directly
1048      registered in the MBean Server will be empty if the MXBean does
1049      not implement the {@link NotificationBroadcaster} interface.
1050      Otherwise, it will be the result of calling {@link
1051      NotificationBroadcaster#getNotificationInfo()} at the time the MXBean
1052      was registered. Even if the result of this method changes
1053      subsequently, the result of {@code MBeanInfo.getNotifications()}
1054      will not. The list returned for an MXBean that is constructed
1055      using the {@link StandardMBean} or {@link StandardEmitterMBean}
1056      class is derived in the same way as for Standard MBeans.</p>
1057
1058    <p>The {@link Descriptor} for all of the
1059      {@code MBeanAttributeInfo}, {@code MBeanParameterInfo}, and
1060      {@code MBeanOperationInfo} objects contained in the {@code MBeanInfo}
1061      will have a field {@code openType} whose value is the {@link OpenType}
1062      specified by the mapping rules above. So even when {@code getType()}
1063      is "{@code int}", {@code getDescriptor().getField("openType")} will
1064      be {@link SimpleType#INTEGER}.</p>
1065
1066    <p>The {@code Descriptor} for each of these objects will also have a
1067      field {@code originalType} that is a string representing the Java type
1068      that appeared in the MXBean interface. The format of this string
1069      is described in the section <a HREF="#type-names">Type Names</a>
1070      below.</p>
1071 
1072    <p>The {@code Descriptor} for the {@code MBeanInfo} will have a field
1073      {@code mxbean} whose value is the string "{@code true}".</p>
1074
1075 
1076    <h3><a name="type-names">Type Names</a></h3>
1077
1078    <p>Sometimes the unmapped type <em>T</em> of a method parameter or
1079    return value in an MXBean must be represented as a string. If
1080    <em>T</em> is a non-generic type, this string is the value
1081    returned by {@link Class#getName()}. Otherwise it is the value of
1082    <em>genericstring(T)</em>, defined as follows:
1083
1084    <ul>
1085
1086      <li>If <em>T</em> is a non-generic non-array type,
1087      <em>genericstring(T)</em> is the value returned by {@link
1088      Class#getName()}, for example {@code "int"} or {@code
1089      "java.lang.String"}.
1090
1091      <li>If <em>T</em> is an array <em>E[]</em>,
1092      <em>genericstring(T)</em> is <em>genericstring(E)</em> followed
1093      by {@code "[]"}. For example, <em>genericstring({@code int[]})</em>
1094      is {@code "int[]"}, and <em>genericstring({@code
1095      List<String>[][]})</em> is {@code
1096      "java.util.List<java.lang.String>[][]"}.
1097
1098    <li>Otherwise, <em>T</em> is a parameterized type such as {@code
1099    List<String>} and <em>genericstring(T)</em> consists of the
1100    following: the fully-qualified name of the parameterized type as
1101    returned by {@code Class.getName()}; a left angle bracket ({@code
1102    "<"}); <em>genericstring(A)</em> where <em>A</em> is the first
1103    type parameter; if there is a second type parameter <em>B</em>
1104    then {@code ", "} (a comma and a single space) followed by
1105    <em>genericstring(B)</em>; a right angle bracket ({@code ">"}).
1106
1107    </ul>
1108
1109    <p>Note that if a method returns {@code int[]}, this will be
1110      represented by the string {@code "[I"} returned by {@code
1111      Class.getName()}, but if a method returns {@code List<int[]>},
1112      this will be represented by the string {@code
1113      "java.util.List<int[]>"}.
1114      
1115    <h3>Exceptions</h3>
1116
1117    <p>A problem with mapping <em>from</em> Java types <em>to</em>
1118      Open types is signaled with an {@link OpenDataException}. This
1119      can happen when an MXBean interface is being analyzed, for
1120      example if it references a type like {@link java.util.Random
1121      java.util.Random} that has no getters. Or it can happen when an
1122      instance is being converted (a return value from a method in an
1123      MXBean or a parameter to a method in an MXBean proxy), for
1124      example when converting from {@code SortedSet<String>} to {@code
1125      String[]} if the {@code SortedSet} has a non-null {@code
1126      Comparator}.</p>
1127
1128    <p>A problem with mapping <em>to</em> Java types <em>from</em>
1129      Open types is signaled with an {@link InvalidObjectException}.
1130      This can happen when an MXBean interface is being analyzed, for
1131      example if it references a type that is not
1132      <em>reconstructible</em> according to the rules above, in a
1133      context where a reconstructible type is required. Or it can
1134      happen when an instance is being converted (a parameter to a
1135      method in an MXBean or a return value from a method in an MXBean
1136      proxy), for example from a String to an Enum if there is no Enum
1137      constant with that name.</p>
1138
1139    <p>Depending on the context, the {@code OpenDataException} or
1140      {@code InvalidObjectException} may be wrapped in another
1141      exception such as {@link RuntimeMBeanException} or {@link
1142      UndeclaredThrowableException}. For every thrown exception,
1143      the condition <em>C</em> will be true: "<em>e</em> is {@code
1144      OpenDataException} or {@code InvalidObjectException} (as
1145      appropriate), or <em>C</em> is true of <em>e</em>.{@link
1146      Throwable#getCause() getCause()}".</p>
1147
1148   @since 1.6
1149*/

1150
1151@Documented JavaDoc
1152@Retention JavaDoc(RetentionPolicy.RUNTIME)
1153@Target JavaDoc(ElementType.TYPE)
1154public @interface MXBean {
1155    /**
1156       True if the annotated interface is an MXBean interface.
1157       @return true if the annotated interface is an MXBean interface.
1158    */

1159    boolean value() default true;
1160}
1161
Popular Tags