File: FunctionalSpec.html

package info (click to toggle)
gmbal 4.0.0-b002-1.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid
  • size: 1,124 kB
  • sloc: java: 10,351; xml: 241; makefile: 2
file content (1789 lines) | stat: -rw-r--r-- 81,012 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<!--

    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.

    Copyright (c) 2008-2018 Oracle and/or its affiliates. All rights reserved.

    The contents of this file are subject to the terms of either the GNU
    General Public License Version 2 only ("GPL") or the Common Development
    and Distribution License("CDDL") (collectively, the "License").  You
    may not use this file except in compliance with the License.  You can
    obtain a copy of the License at
    https://oss.oracle.com/licenses/CDDL+GPL-1.1
    or LICENSE.txt.  See the License for the specific
    language governing permissions and limitations under the License.

    When distributing the software, include this License Header Notice in each
    file and include the License file at LICENSE.txt.

    GPL Classpath Exception:
    Oracle designates this particular file as subject to the "Classpath"
    exception as provided by Oracle in the GPL Version 2 section of the License
    file that accompanied this code.

    Modifications:
    If applicable, add the following below the License Header, with the fields
    enclosed by brackets [] replaced by your own identifying information:
    "Portions Copyright [year] [name of copyright owner]"

    Contributor(s):
    If you wish your version of this file to be governed by only the CDDL or
    only the GPL Version 2, indicate your decision by adding "[Contributor]
    elects to include this software in this distribution under the [CDDL or GPL
    Version 2] license."  If you don't indicate a single choice of license, a
    recipient has the option to distribute your version of this file under
    either the CDDL, the GPL Version 2 or to extend the choice of license to
    its licensees as provided above.  However, if you add GPL Version 2 code
    and therefore, elected the GPL Version 2 license, then the option applies
    only if the new code is made subject to such option by the copyright
    holder.

-->

<!-- 
  Document : FunctionalSpec
  Created on : Nov 17, 2008, 4:25:47 PM
  Author : ken
-->

  <title>GMBAL Functional Spec</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <style type="text/css" title="Amaya theme">
/* Modern style for Amaya Editor Lite */

/* default rules for the whole document */
body {
    font-size: 12pt;
    font-family: Helvetica, Arial, sans-serif;
    font-weight: normal;
    font-style: normal;
    color: black;
    background-color: white;
    line-height: 1.2em;
    margin-left: 4em;
    margin-right: 2em;
   }

/* paragraphs */
pre {
    color: Green;
    }

p  {
    padding: 0;
    margin-top: 1em;
    margin-bottom: 1em;
    text-align: left;
   }

/* headings */
h1 {
    font-size: 180%;
    font-weight: bold;
    font-style: normal;
    font-variant: small-caps;
    text-align: left;
    padding: 0;
    margin-top: 1.7em;
    margin-bottom: 1.7em;
   }
h2 {
    font-size: 150%;
    font-weight: bold;
    font-style: normal;
    padding: 0;
    margin-top: 1.5em;
    margin-bottom: 1.1em;
   }
h3 {
    font-size: 130%;
    font-weight: bold;
    font-style: normal;
    padding: 0;
    margin-top: 1.3em;
    margin-bottom: 1.1em;
   }
h4 {
    font-size: 110%;
    font-weight: bold;
    font-style: normal;
    padding: 0;
    margin-top: 1.1em;
    margin-bottom: 1.1em;
   }
h5 {
    font-size: 100%;
    font-weight: bold;
    font-style: italic;
    padding: 0;
    margin-top: 1em;
    margin-bottom: 1em;
   }
h6 {
    font-size: 100%;
    font-weight: normal;
    font-style: italic;
    padding: 0;
    margin-top: 1em;
    margin-bottom: 1em;
   }

/* divisions */
div {
    padding: 0;
    margin-top: 0em;
    margin-bottom: 0em;
   }

/* lists */
ul, ol {
    padding: 0 0 0 3em;
    margin-top: 1em;
    margin-bottom: 1em;
   }
ul ul, ol ol, ul ol, ol ul {
    margin-top: 1em;
    margin-bottom: 1em;
   }
li {
    padding: 0;
    margin-top: 1em;
    margin-bottom: 1em;
    text-align: left;
   }
li p {
    margin-top: 1em;
    margin-bottom: 1em;
   }
dl {
    padding: 0;
    margin-top: 1em;
    margin-bottom: 1em;
    margin-left: 1em;
   }
dl dl {
    margin-top: 0em;
    margin-bottom: 0em;
   }
dt {
    padding: 0;
    font-weight: bold;
    margin-top: .3em;
    margin-bottom: .3em;
   }
dd {
    padding: 0;
    margin-top: .3em;
    margin-left: 3em;
    margin-bottom: .3em;
   }
dl p {
    margin-top: .3em;
    margin-bottom: .3em;
   }

/* inline */
strong {
    font-weight: bold;
   }
em {
    font-style: italic;
   }
code {
    font-family: Courier New, Courier, monospace;
   }
ins {
    background-color: yellow;
    text-decoration: underline;
   }
del {
    text-decoration: line-through;
   }

/* anchors */
a[href] {
    color: blue;
    text-decoration: underline;
   }

/* end */
  </style>
</head>
<body>
<h1>GlassFish MBean Annotation Library (gmbal)</h1>
<h1>Functional Specification</h1>
by Ken Cavanaugh<br>
Version 1.0 (for GlassFish v3 FCS)<span
 style="background-color: rgb(250, 255, 221);"></span><br>
12/11/09<span style="background-color: rgb(255, 249, 200);"></span><br>
<h2>1. Introduction</h2>
<p>The GlassFish MBean Annotation Library (gmbal, pronounced as in
"gumball")
is a runtime annotation processor that creates Open MBeans. This is
useful for
creating a management API for existing code with minimal effort.&nbsp;
It is
intended to be applied to existing modules (which may be OSGi bundles
in
GlassFish v3, or any other packaging model including standard jar
files), but
could be used anywhere that it is desired to combine the definition of
the
management API with the module API and implementation.</p>
<p>Note that gmbal is not limited to use in GlassFish. Gmbal is
completely independent of GlassFish, and may be used in a context where
GlassFIsh is not present. However, when a gmbal-enabled module in used
in
GlassFish V3, that module will automatically be manageable using
GlassFish V3
admin tools.</p>
<p>There are really two parts to creating a management API for a
module:
instrumenting the module implementation, and providing a client
interface that
may be accessed remotely. This is closely related to the AMX work in
GFv3.&nbsp; AMX defines the interface for AMX MBeans, and provides
tools and libraries for clients accessing AMX MBeans.&nbsp; Gmbal is a
library that provides a mechanism for implementing AMXv3-compliant
MBeans.<br>
</p>
<h3>1.1. Alignment with related projects</h3>
JMX is also defining similar annotations in JSR 255 for JDK 7.&nbsp;
The JSR 255 spec is available at the download <a
 href="http://jcp.org/aboutJava/communityprocess/edr/jsr255/index.html">page</a>.
Gmbal is mostly aligned with the JSR 255
annotations.&nbsp;
<br>
<br>
The similarities include:<br>
<ul>
  <li><a href="gmbal/javadoc/org/glassfish/gmbal/ManagedAttribute.html">@ManagedAttribute</a>
is the same, except that gmbal allows overriding the id.</li>
  <li><a href="gmbal/javadoc/org/glassfish/gmbal/ManagedOperation.html">@ManagedOperation</a>
is the same, except that gmbal allows overriding the id.</li>
  <li><a href="gmbal/javadoc/org/glassfish/gmbal/DescriptorKey.html">@DescriptorKey</a>
is the same.</li>
  <li><a href="gmbal/javadoc/org/glassfish/gmbal/DescriptorFields.html">@DescriptorFields</a>
is the same.</li>
  <li><a href="gmbal/javadoc/org/glassfish/gmbal/Description.html">@Description</a>
is similar to JSR 255, but does not support a bundleBaseName attribute.
The bundle is set in gmbal through the
ManagedObjectManager.setResourceBundle call.<br>
  </li>
</ul>
Differences:<br>
<ul>
  <li>The packaging is necessarily different: org.glassfish.gmbal for
gmbal, javax.management for JSR 255.</li>
  <li>Gmbal uses <a
 href="gmbal/javadoc/org/glassfish/gmbal/ManagedObject.html">@ManagedObject</a>
instead of @MBean (part of JSR 255) or <a
 href="http://java.sun.com/javase/6/docs/api/javax/management/MXBean.html">@MXBean</a>.</li>
  <li>Gmbal only supports attribute change notifications, so
the @NotificationInfo annotation (from JSR 255) does not exist in
Gmbal.&nbsp; See "<a href="#3.2.3._register_and_registerAtRoot">register
and registerAtRoot</a>" for a discussion on notification support.<br>
  </li>
  <li>Gmbal has an <a
 href="gmbal/javadoc/org/glassfish/gmbal/ManagedData.html">@ManagedData</a>
annotation to define the mapping of data types into CompositeData,
while JSR 255 follows MXBeans and simply assumes that all methods that
follow the JavaBeans patterns define read-only attributes.</li>
  <li>Gmbal supports an <a
 href="gmbal/javadoc/org/glassfish/gmbal/MBeanType.html">@AMXMetadata</a>
annotation, but this is really just an extension to the descriptor
annotation mechanism borrowed from JMX ModelMBeans.&nbsp; The
@AMXMetadata annotation is provided to support AMX-specific metadata.</li>
  <li>Gmbal includes <a
 href="gmbal/javadoc/org/glassfish/gmbal/ParameterNames.html">@ParameterNames</a>
to provide reasonable names for the arguments on MBean
operations.&nbsp; JSR 255 does not currently have such a mechanism,
because JDK 7 will have an extension to Java reflection that captures
the argument names on methods.</li>
  <li>Gmbal includes <a
 href="gmbal/javadoc/org/glassfish/gmbal/ObjectNameKey.html">@NameValue</a>
to make it easy to define the value of the "name" field in the
ObjectName. This makes registration of object as MBeans slightly
simpler.</li>
  <li>Gmbal includes <a
 href="gmbal/javadoc/org/glassfish/gmbal/IncludeSubclass.html">@IncludeSubclass</a>,
which allows limited (and closed) polymorphism for CompositeData.&nbsp;
This partially solves the problem of mapping a group of types sharing
type Base that appear as (for example) attributes with type
List&lt;Base&gt;.</li>
  <li>Gmbal includes <a
 href="gmbal/javadoc/org/glassfish/gmbal/InheritedAttribute.html">@InheritedAttribute</a>(<a
 href="gmbal/javadoc/org/glassfish/gmbal/InheritedAttributes.html">s</a>)
to allow using methods inherited from super classes or super interfaces
that cannot be annotated as attribute and operations.</li>
  <li>Gmbal is more limited currently in mapping OpenType -&gt; Java
type than JMX is, as this does not seem to be a feature that we need.<br>
  </li>
</ul>
Note that there are two complimentary ways to define MBeans: MXBeans
and
annotations.&nbsp; MXBeans are somewhat more convenient to use in cases
where EVERY
method in a class or interface is part of the management interface,
whereas
annotations are more convenient for adding a management interface to
existing
code. But both mechanisms share most of the same rules for MXBean
mapping from
Java types to Open types as discussed in "<a
 href="#4.3._OpenType_mapping_">OpenType Mapping</a>".<br>
<br>
AMX in GlassFish v3 is being generalized to define exactly what an
MBean must
do to be manageable in the GlassFish v3 admin tools (see Lloyd's <a
 href="https://glassfish.dev.java.net/nonav/v3/admin/planning/V3Changes/V3_AMX_SPI.html">GlassFish
V3 AMX SPI</a> specification). Gmbal will follow all mandatory and most
of the
optional requirements of this specification so that any module that
uses gmbal
to define MBeans will automatically participate in the GFv3 admin tools
when run in a GFv3 container.&nbsp; However, this will not prevent
the use of
gmbal in these same modules as a standalone MBean definition library.<br>
<br>
This last point needs a little more explanation.&nbsp; The main
interface that
matters for running in or out of a GFv3 container is
ManagedObjectManagerFactory.create<span style="font-style: italic;">XXX</span>
(<span style="font-style: italic;">XXX</span> is either Standalone or
Federated).
The createStandalone method is needed for running outside of GFv3, and
takes
the domain name as an argument. createFedederated must be called inside
of
GFv3, and this requires the AMXv3-compliant ObjectName of the
ManagedObjectManager root
MBean's
parent.&nbsp; Calling the appropriate method is probably best handled
in most cases
by having an OSGi bundle for a module that is responsible for
integrating the
module into GFv3.&nbsp; <br>
<br>
For example, the orb-iiop bundle integrates the standalone ORB bundles
into GFv3. orb-iiop handles
registration of all of the GFv3-specific interceptors and other
initialization
when the GFv3 ORB instance is created. orb-iiop will also need to set
the ORB property com.sun.corba.ee.ORBGmbalRootParentName to the string
representation of the ObjectName of the ORB's gmbal root parent.&nbsp;
The ORB will then use this property to call either createStandalone (if
it is not set) or createFederated (with the value of the property as
the ObjectName passed into the call).<br>
<h3>1.2. Similar projects</h3>
Besides JSR 255 (discussed in the previous section), there are at least
two other
projects that also define MBeans using annotations.<br>
<br>
The Spring project also defines a set of <a
 href="http://static.springframework.org/spring/docs/2.0.x/reference/jmx.html#jmx-interface-annotations">annotations</a>
to use for creating
MBeans.&nbsp; Eamonn McManus has pointed to this as one of the starting
points for JSR 255 in a blog <a
 href="http://weblogs.java.net/blog/emcmanus/archive/2007/08/defining_mbeans.html">post</a>
from August 2007.&nbsp; JSR 255 and Spring share the @ManagedAttribute
and @ManagedOperation annotations, but the Spring annotations
include a description fields, whereas JSR 255 has moved the description
into a separate annotation (as I have
in gmbal as well).<br>
<br>
The WebObject project from INRIA in France has created the <a
 href="http://spoon.gforge.inria.fr/SpoonJMX/Main">SpoonJMX</a>
project, which
also allows the use of annotations to define MBeans. SpoonJMX uses
@ManagedResource to define an MBean class.&nbsp; It
uses @ManagedAttribute and @ManagedOperation as in the other
systems.&nbsp; SpoonJMX defines a @ObjectKeyName annotation,
which I have adopted for use in gmbal as well under the name of
@NameValue.&nbsp; SpoonJMX also
defines more attributes on the annotations than
either gmbal or JSR 255.<br>
<h2>2. The Management Data Model</h2>
Gmbal supports a simple hierarchical model of management data as
defined in JSR
77 and AMX.<br>
<img style="width: 730px; height: 507px;" alt="Gmbal Class Diagram"
 src="Gmbal.png"><br>
The components of the data model are as follows:<br>
<ul>
  <li>A ManagedObjectManager acts as a container for all state related
to a particular usage of gmbal. This includes:
    <ul>
      <li>A domain to use for all ObjectNames created in this
ManagedObjectManager.</li>
      <li>A rootParentName, which is the ObjectName of the parent of
the ManagedObjectManager.</li>
      <li>A root object, which represents the top of the tree of MBean
managed by the ManagedObjectManager.<br>
      </li>
    </ul>
  </li>
  <li>From a POJO with annotations, an MBeanImpl is constructed, which
implements the dynamic MBean API.&nbsp; This dynamic MBean is
associated with additional classes:
    <ul>
      <li>0 or more Attributes, which may be getters or setters or both
(note that AMX will give as at least Name, Parent, and Children
attributes).<br>
      </li>
      <li>0 or more Operations, which may be invoked.</li>
      <li>Metadata, represented by ModelMBeanInfoSupport (so that
metadata Descriptors are available on JDK 5 as well as JDK 6). The
Metadata is extensible through the use of the @DescriptorKey and
@DescriptorField meta-annotations.<br>
      </li>
      <li>A single parent MBeanImpl, which may be null (this is one end
of the contains relation).</li>
      <li>0 or more child MBeanImpls (this is the other end of the
contains relation).</li>
      <li>Following AMXv3, the ObjectName of the MBean will contain 3
name/value pairs:</li>
      <ul>
        <li>pp, which is the AMXv3 parent path, or the path name of the
parent of this MBean</li>
        <li>type, which is derived from the Class using annotations or
other mechanisms</li>
        <li>name, which is derived either from the registration call,
or a method on the object.&nbsp; The name is absent in the case of a
singleton.&nbsp; In any case, the type and name (if present) must be
unique within the scope of the parent.<br>
        </li>
      </ul>
    </ul>
  </li>
  <li>Attributes and Operations have ids, which are generally derived
from the name of the annotated method as discussed <a
 href="#4.1._Processing_of_method_names_for_IDs">here</a>, but the id
may also be specified in the @<a
 href="gmbal/javadoc/org/glassfish/gmbal/ManagedAttribute.html">ManagedAttribute</a>
and @<a href="gmbal/javadoc/org/glassfish/gmbal/ManagedOperation.html">ManagedOperation</a>
annotations, as well as in the @<a
 href="gmbal/javadoc/org/glassfish/gmbal/InheritedAttribute.html">InheritedAttribute</a>
annotation.<br>
  </li>
</ul>
Note that all values consumed or produced by Attributes and Operations
are
instances of OpenTypes.<br>
<br>
This diagram is a simplification of the actual implementation of
gmbal.&nbsp; In
particular,&nbsp; the metadata, attributes, and operations are
maintained in a
MBeanSkeleton
class, which is shared by all MBeanImpls for instances of the same
class.&nbsp; The TypeConverter
that handles conversion between Java types and the corresponding
OpenType is also
not
included here.<br>
<h2>3. Interfaces</h2>
Javadocs are <a href="gmbal/javadoc/index.html">available</a> as part
of the
gmbal project.&nbsp; <br>
<br>
There are basically 3 elements to the gmbal API:<br>
<ol>
  <li>class ManagedObjectManagerFactory, which provides factory methods
for creating instance of the ManagedObjectManager interface.</li>
  <li>interface ManagedObjectManager, which provides
register/deregister methods (and a number of other capabilities).</li>
  <li>A number of annotations.<br>
  </li>
</ol>
Here is a summary of the annotations:<br>
<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
 cellspacing="2">
  <tbody>
    <tr>
      <td style="vertical-align: top; font-weight: bold;">Annotation
Class<br>
      </td>
      <td style="vertical-align: top; font-weight: bold; width: 20%;">Annotation
Fields<br>
      </td>
      <td style="vertical-align: top; font-weight: bold;">Applicable
Element Type<br>
      </td>
      <td style="vertical-align: top;"><span style="font-weight: bold;">Relation
to JSR 255</span><br>
      </td>
      <td style="vertical-align: top; font-weight: bold;">Purpose<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@ManagedObject<br>
      </td>
      <td style="vertical-align: top;">none<br>
      </td>
      <td style="vertical-align: top;">Class or Interface<br>
      </td>
      <td style="vertical-align: top;">255 uses @MXBean<br>
      </td>
      <td style="vertical-align: top;">Defines a class whose instances
are processed into MBeans.<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@ManagedData<br>
      </td>
      <td style="vertical-align: top;">String name (defaults to class
name)<br>
      </td>
      <td style="vertical-align: top;">Class or Interface<br>
      </td>
      <td style="vertical-align: top;">MXBeans assume all methods are
in CompositeData<br>
      </td>
      <td style="vertical-align: top;">Defines a class whose instances
are process into Open data for Open Mbeans.<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@ManagedAttribute<br>
      </td>
      <td style="vertical-align: top;">String id (defaults to value
from Method name)<br>
      </td>
      <td style="vertical-align: top;">Method or field<br>
      </td>
      <td style="vertical-align: top;">Same<br>
      </td>
      <td style="vertical-align: top;">Defines a method or field that
represents
an attribute either in ManagedData or ManagedObject<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@ManagedOperation<br>
      </td>
      <td style="vertical-align: top;">String id (defaults to value
from Method name)<br>
Impact impact (defaults to UNKNOW; Impact enum corresponds to
MBeanOperationInfo impact values)<br>
      </td>
      <td style="vertical-align: top;">Method<br>
      </td>
      <td style="vertical-align: top;">Same<br>
      </td>
      <td style="vertical-align: top;">Defines a method that represents
an operation in ManagedObject <br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@Description<br>
      </td>
      <td style="vertical-align: top;">String value<br>
      <br>
String key (the key to use in a generated resource bundle; default ""
means to derive key from name of annotated element)<br>
      </td>
      <td style="vertical-align: top;">Class, Interface,&nbsp; Method,
or Field<br>
      </td>
      <td style="vertical-align: top;">Same (but JSR 255 includes I18N)<br>
      </td>
      <td style="vertical-align: top;">Defines the descriptive text
associated with a Class, Interface, or Method. This may require I18N,
as discussed <a href="#4.2._I18N_support">here</a>.<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@IncludeSubclass<br>
      </td>
      <td style="vertical-align: top;">Class[] value<br>
      </td>
      <td style="vertical-align: top;">Class or Interface for
ManagedData<br>
      </td>
      <td style="vertical-align: top;">N/A<br>
      </td>
      <td style="vertical-align: top;">Lists subclasses of the
annotated class that should also be scanned for annotations which are
included only on instances of the appropriate type<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@NameValue<br>
      </td>
      <td style="vertical-align: top;">none<br>
      </td>
      <td style="vertical-align: top;">Method<br>
      </td>
      <td style="vertical-align: top;">N/A<br>
      </td>
      <td style="vertical-align: top;">Defines a method (must be a
getter) whose result is the value of the name attribute in the
ObjectName of the MBean for an instance of the class<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@ParameterNames<br>
      </td>
      <td style="vertical-align: top;">String[] value (defaults to "")
(if present, must have same length as number of arguments in the
annotated method)<br>
      </td>
      <td style="vertical-align: top;">Method<br>
      </td>
      <td style="vertical-align: top;">N/A (JSR 255 will take this
information from reflection, which will make arg names available in JDK
7)<br>
      </td>
      <td style="vertical-align: top;">Defines the method names to be
used on an MBean operation. If this annotation is not present or has
the default value, the names will be arg<span
 style="font-style: italic;">Num, </span>where <span
 style="font-style: italic;">Num</span> is the position of the argument
starting from 0<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@InheritedAttribute<br>
      </td>
      <td style="vertical-align: top;">
      <ul>
        <li>String description</li>
        <li>String id (default "" which means take from method name)</li>
        <li>String methodName (default "" which means use id)</li>
      </ul>
one of methodName or id must NOT be ""<br>
      <br>
      </td>
      <td style="vertical-align: top;">Class or Interface<br>
      </td>
      <td style="vertical-align: top;">N/A<br>
      </td>
      <td style="vertical-align: top;">Defines a method inherited from
a class that cannot be annotated as an attribute. See "<a
 href="#3.2.8._addAnnotation">addAnnotation</a>" for a discussion of
the use of this annotation.<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@InheritedAttributes<br>
      </td>
      <td style="vertical-align: top;">InheritedAttribute[] value<br>
      </td>
      <td style="vertical-align: top;">Class or Interface<br>
      </td>
      <td style="vertical-align: top;">N/A<br>
      </td>
      <td style="vertical-align: top;">Allows including multiple
inherited attributes<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@AMXMetadata<br>
      </td>
      <td style="vertical-align: top;">
      <ul>
        <li>boolean isSingleton() (true&nbsp; if only one MBean of this
type is allowed as a child of&nbsp; another MBean)</li>
        <li>String group() (value is the group for this mbean, defaults
to "other")</li>
        <li>String[] subTypes() (value is the list of allowable types
for children of this bean)</li>
        <li>String genericInterfaceName() (used in AMX proxy
construction)<br>
        </li>
        <li>&nbsp;boolean immutableInfo() (true if the MBeanInfo
can never change)</li>
        <li>String interfaceClassName() (also used in AMX proxy
construction)<br>
        </li>
        <li>String type() (the type to use in an ObjectName or in an
admin CLI path expression:&nbsp; defaults to class name, but see
also&nbsp; <a href="#filterPrefix">stripPrefix</a>)</li>
      </ul>
&nbsp;(This is just an application of @DescriptorKey, with a little
special support in the gmbal implementation)<br>
      </td>
      <td style="vertical-align: top;">Class or Interface<br>
      </td>
      <td style="vertical-align: top;">N/A (but JMX supports
descriptors; see below)<br>
      </td>
      <td style="vertical-align: top;">Adds GFv3 and AMX specific
metadata to be defined for MBeans (see "<a
 href="#4.4._Metadata_support_">Metadata Support</a>" for more details).<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@DescriptorKey<br>
      </td>
      <td style="vertical-align: top;">String value<br>
      </td>
      <td style="vertical-align: top;">Annotation method<br>
      </td>
      <td style="vertical-align: top;">same as JSR 255<br>
      </td>
      <td style="vertical-align: top;">Define metadata that can be
added to any MBean (see "<a href="#4.4._Metadata_support_">Metadata
Support</a>" for details)<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">@DescriptorField<br>
      </td>
      <td style="vertical-align: top;">String value (must be name=value)<br>
      </td>
      <td style="vertical-align: top;">Class, Interface, or Method<br>
      </td>
      <td style="vertical-align: top;">same as JSR 255<br>
      </td>
      <td style="vertical-align: top;">Define metadata directly on
MBean (See "<a href="#4.4._Metadata_support_">Metadata Support</a>" for
details)<br>
      </td>
    </tr>
  </tbody>
</table>
<br>
Note that @ManagedAttribute and @Description may be used on fields.
There is however a limitation: any such field MUST be final, and have a
known immutable type.&nbsp; This is necessary to guarantee that access
to the field is safe in the presence of multiple thread.&nbsp; The
legal types are basically the SimpleTypes from JMX OpenType, with a
couple of additions:<br>
<ul>
  <li>The primitives (boolean, byte, char, short, int, long, float,
double) and the corresponding java.lang wrapper classes (Boolean, Byte,
Character, Short, Integer, Long, Float, Double).</li>
  <li>String</li>
  <li>BigDecimal, BigInteger</li>
  <li>Date</li>
  <li>ObjectName</li>
  <li>Class</li>
  <li>Number</li>
  <li>Object<br>
  </li>
</ul>
<h3>3.1. The ManagedObjectManagerFactory</h3>
The ManagedObjectManagerFactory is primarily used to create
ManagedObjectManagers.&nbsp; It is the only concrete class in the gmbal
API, which is defined in the package org.glassfish.gmbal.&nbsp;
Obviously the implementation has other concrete classes, but these are
contained in subpackages under org.glassfish.gmbal.<br>
<h4>3.1.1. getMethod</h4>
This is a simple wrapper around Class.getDeclaredMethod that converts
the
checked exceptions from getDeclaredMethod into unchecked
exceptions.&nbsp; It is
intended for use with the <a href="#addAnnotation">addAnnotation</a>
method.<br>
<h4><a name="3.1.2._create"></a>3.1.2. create</h4>
There are two versions of create: createStandalone( String ) and
createFederated( ObjectName ).&nbsp;
createStandalone( String ) is used to create a standalone hierarchy:
the String is the
domain to use for all ObjectNames created from the resulting
ManagedObjectManager.&nbsp; In this version, the root has no parent.<br>
<br>
createFederated( ObjectName ) is used to create a hierarchy of MBeans
that are rooted
under a parent MBean that is not managed by the created instance of
ManagedObjectManager.&nbsp; In this case, the parent of the
ManagedObjectManager is
identified by the object name (called the rootParentName) that is
passed to the
create call.&nbsp; Note that the root parent MBean MUST be managed by
the same
MBeanServer as the ManagedObjectManager.&nbsp; The ObjectName MUST be
an AMX-compliant ObjectName: in particular, it MUST define pp, type,
and
name attributes.<br>
<br>
Note that createFederated must obey the parent-child restriction in
AMX.&nbsp; That is, a child cannot be created<br>
before its parent has been created.&nbsp; It is possible that the root
parent ObjectName passed to createFederated does not correspond to a
valid MBean in the MBeanServer at the time that createFederated is
called.&nbsp; In this case, the Gmbal ManagedObjectManager&nbsp;
created by the createFederated call must defer registration of its
MBeans until after the root parent has been registered.&nbsp; The MOM
monitors the root parent in the MBeanServer, registering and
de-registering all MBeans in the mom's tree as the root parent is
registered and de-registered.<br>
<br>
For examples of the usage of these methods, see "<a
 href="#4.6._Using_Gmbal_">Using Gmbal</a>".<br>
<h3>3.2. The ManagedObjectManager</h3>
The ManagedObjectManager is the main API for gmbal.&nbsp; It contains a
tree of
MBeans with a single root,<br>
which may optionally be federated into a large MBean hierarchy.<br>
<br>
The most important methods are createRoot, register, and
unregister.&nbsp; Any
application of gmbal must use these methods.&nbsp; For examples of the
usage of the key methods, see "<a href="#4.6._Using_Gmbal_">Using Gmbal</a>".<br>
<h4>3.2.1. createRoot</h4>
There are several methods to create a root in the
ManagedObjectManager.&nbsp;
createRoot() creates a root that simply acts as an AMX container.&nbsp;
Its type
and name are both set to GMBALROOT.<br>
<br>
createRoot( Object ) and createRoot( Object, String ) both use the
given object
as the root, and just as in the register methods, these methods create
an MBean
from the Object using the annotations on its class. The createRoot(
Object )
method will derive the name from the object itself by calling the
@NameValue method from the class.&nbsp; If no such method is
available, the
name is set to the type value.&nbsp; The second method allows the name
to specified
explicitly.&nbsp; This can be useful in case where either
@NameValue is not
used, or there are multiple ManagedObjectManager instances with the
same root
type that share the same parent.&nbsp; In this case, it is essential
that each root
have a distinct name.last.&nbsp; There is also a createRoot() method,
which creates a simple internal root that only provides the required
AMXv3 attributes.<br>
<br>
createRoot may only be called when the ManagedObjectManager does not
already
contain a root. This is true immediately after a
ManagedObjectManagerFactory.create call, or after unregistering the
root.<br>
<h4>3.2.2. getRoot</h4>
getRoot returns the current root of the ManagedObjectManager.&nbsp; If
no root is
available, getRoot throws an IllegalStateException.<br>
<h4><a name="3.2.3._register_and_registerAtRoot"></a>3.2.3. register
and registerAtRoot</h4>
There are two forms of register: register( Object parent, Object obj )
and
register( Object parent, Object obj, String name ).&nbsp; The first
form obtains
the name from obj (by using @NameValue),
the second allows explicit specification of the name.&nbsp; The
returned result is
an instance
of NotificationEmitter that may be used to register a
NoticationListener to
listen for attribute change notifications on the
MBean that was created for obj.&nbsp; <br>
<br>
There are also two forms of registerAtRoot: registerAtRoot( Object obj
) and
registerAtRoot( Object obj, String name).&nbsp; These methods are
exactly
equivalent to mom.register( mom.getRoot(), obj ) and mom.register(
mom.getRoot(), obj, name ). <br>
<br>
All of these methods can only be called after a successful createRoot
call.<br>
<h4><a name="3.2.4._unregister"></a>3.2.4. unregister</h4>
unregister( Object ) unregisters an object that was previously
registered.&nbsp; It
also deletes any children of the object in depth-first order.&nbsp;
Unregister
removes the generated MBean from the ManagedObjectManager and also
unregisters
the MBean from the ManagedObjectManager's MBeanServer.<br>
<br>
Unregister can only be called after a successful createRoot call.<br>
<h4>3.2.5. getObject/getObjectName</h4>
The register methods return a NotificationEmitter which can be used to
register
a NotificationListener to listen for attribute change events.&nbsp; But
sometimes
access to the ObjectName is needed.&nbsp; getObjectName returns the
ObjectName that
was created for an object that was passed to the register method.&nbsp;
getObject
is used to handle the opposite case: going from the ObjectName to the
registered Object.&nbsp; Note that in both case the registered Object
is the
implementation object passed to a register method, NOT the internally
created
dynamic MBean (which is not directly provided).<br>
<br>
These methods can only be called after a successful createRoot call.<br>
<h4>3.2.6. stripPrefix and stripPackagePrefix<a name="filterPrefix"></a></h4>
A type prefix is simply a prefix of a fully qualified Java class name.
By
default, the MBean ObjectName type field is set to the full qualified
class
name of the implementation class, stripped of the longest type prefix
of the
class name.&nbsp; For example, in CORBA the type prefixes are set to:<br>
<br>
<div style="margin-left: 40px;">
com.sun.corba.se<br>
com.sun.corba.se.spi<br>
com.sun.corba.se.spi.orbutil<br>
com.sun.corba.se.impl<br>
com.sun.corba.se.impl.orbutil<br>
<br>
</div>
This helps keep the ObjectNames to a reasonable length.&nbsp;
Applications of gmbal
are also free to specify the exact type name to use through an
annotation.<br>
<br>
stripPackagePrefix is used to indicate that ALL package prefixes should
be removed from the class name for the default type.<br>
<br>
These methods may only be called before a successful createRoot call.<br>
<h4>3.2.7. <a name="MBeanServer_and_ResourceBundle"></a>MBeanServer
and
ResourceBundle</h4>
Accessors (getter and setter) are provided for the MBeanServer and the
ResourceBundle.<br>
<br>
The MBeanServer is used for all register and unregister operations in
the
ManagedObjectManager instance. It defaults to the<br>
platform MBeanServer.<br>
<br>
The ResourceBundle is used to internationalize all descriptions.&nbsp;
If set, the
description value is used as a key in the resource bundle,<br>
otherwise the description value is taken as the actual description.<br>
<h4><a name="3.2.8._addAnnotation"></a>3.2.8. <a name="addAnnotation"></a>addAnnotation</h4>
The best way to explain this method is to start with an example.&nbsp;
CORBA
defines a class org.omg.PortableServer.Servant.&nbsp;&nbsp; The
definition of Servant is a standard, and so I cannot add annotations to
the
source code for Servant.&nbsp; Gmbal is flexible enough that we can put
the annotation almost anywhere, so what are the possible
subclasses of Servant? Mostly one subclass is used in GlassFish for
dynamic RMI-IIOP: ReflectiveTie,
but others are possible, including Ties generated by the idlj
compiler.&nbsp; We also cannot add non-standard
annotations to standard-compliant code generated by a code generator.<br>
<br>
This becomes an issue when adding annotations to things like the ORB's
POA,
which has a method:<br>
<pre>@ManagedData<br>Servant get_servant() { ... }<br></pre>
that I would like to use as an attribute.&nbsp; How should gmbal
represent Servant
in this case?&nbsp; I may want to represent the Servant as ManagedData,
using one or more methods (such as byte[]
_object_id()) on the Servant as attributes, but there is no place that
I can put an annotation for this.<br>
<br>
The solution I have adopted in gmbal is to allow annotations to be
added on
"dummy" classes, and then use&nbsp; ManagedObjectManager.addAnnotation
to add the annotation to the appropriate
type.&nbsp; For example, the above example can be handled by:<br>
<pre>@ManagedData<br>@InheritedAttributes( {<br>    @InheritedAttribute( methodName="_object_id", id="objectId",<br>        description="The Object Id for this Servant" ),<br>    ... // several other methods<br>} )<br>public interface DummyServant {}<br><br>mom.addAnnotation( Servant.class, <br>    DummyServant.class.getAnnotation( ManagedObject.class ) ) ;<br>mom.addAnnotation( Servant.class, <br>    DummyServant.class.getAnnotation( InheritedAttributes.class ) ) ;<br></pre>
This behaves exactly as if the annotations on DummyServant were on
Servant,
allowing the appropriate&nbsp; annotation processing to take place.<br>
<br>
InheritedAttribute can also be used when it is desired to use a method
inherited from a super class as an attribute or operation.&nbsp; This
is useful in the case where the superclass is
a class that for whatever reason cannot be modified with an
annotation.&nbsp; For example, the GlassFish v3 ORB defines an
interface TaggedProfileTemplate (in com.sun.corba.se.spi.ior) as
follows:<br>
<pre>@ManagedData<br>@Description( "A template for creating a TaggedProfile" ) <br>@IncludeSubclass( { com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate.class } )<br>@InheritedAttribute( description="List of TaggedComponents for this template",<br>    methodName="iterator", id="TaggedComponents" )<br>public interface TaggedProfileTemplate extends List&lt;TaggedComponent&gt;, <br>    Identifiable, WriteContents, MakeImmutable<br>{ <br>    ...  <br>}<br></pre>
<p>Here the iterator method is inherited from
List&lt;TaggedComponent&gt;.&nbsp; The iterator() method then has type
Iterator&lt;T&gt;, where T is bound to TaggedComponent. This results in
a CompositeData attribute with id TaggedComponents, which returns an
OpenType which is an array of whatever TaggedComponent maps to
(CompositeData as discussed in "<a href="#4.7._Handling_Polymorphism">Handling
Polymorphism</a>").<br>
</p>
<h4>3.2.9. Debugging support</h4>
Gmbal is a fairly complex system, and it is possible to apply it in
ways that
lead to incorrect results. To avoid problems, following the suggested
patterns in "<a href="#4.6._Using_Gmbal_">Using Gmbal</a>" will
help.&nbsp; Mistakes such as using an @ManagedAttribute operation on a
method that is not a valid attribute should be obvious from the
exception thrown by the register call.&nbsp; But perhaps the problem is
simply that the MBean definition is not exactly what was expected, due
to the pattern of annotations across multiple class and interface
definitions. Some assistance may be needed from gmbal to see what
exactly is happening, and also to aid in identifying bugs in gmbal
itself.<br>
<br>
To help with these kinds of problems, gmbal has several features that
can be useful for
debugging:<br>
<ul>
  <li>setRegistrationDebugLevel( RegistrationDebugLevel level ).&nbsp;
Here the level can be NONE, NORMAL, or FINE.&nbsp; When enabled, this
method causes detailed tracing (more detailed with FINE) of the
operations involved in registering an MBean.</li>
  <li>setRuntimeDebugLevel( boolean flag ).&nbsp; If this is enabled,
the operations involved in getting or setting attributes or calling an
operation on an MBean are traced.</li>
  <li>setTypelibDebug( int level ).&nbsp; This is used to trace typelib
operations.&nbsp; 1 traces only basic operation, while &gt;1 gives full
details (produces a lot of output).<br>
  </li>
  <li>String dumpSkeleton( Object obj ).&nbsp; If obj is an object that
has been registered with the ManagedObjectManager, this returns a
String dump of the MBeanSkeleton object, which provides detailed
information about the exact attributes and operations supported by the
MBean.</li>
</ul>
These operations can be used to get useful information about the
operation of
gmbal.&nbsp; The setXXXDebugLevel methods currently dump<br>
information to System.out, but the code has a flag that can be set to
dump
information to a Logger.&nbsp; The Logger may become the <br>
default dump mechanism in the future.<br>
<h4><a name="3.2.10._Close"></a>3.2.10. Close</h4>
<p>The close call is provided to unregister all MBeans still registered
with the MBeanServer, and to release all internal state maintained by
the ManagedObjectManager. Note that the registered MBeans are
unregistered and destroyed bottom up, to preserve the AMX requirements
that children cannot exist without their parent existing (see section
5.1 "Parent must exist" of the <a
 href="https://glassfish.dev.java.net/nonav/v3/admin/planning/V3Changes/V3_AMX_SPI.html">AMX
SPI specification</a>).<br>
</p>
<h4>3.2.11. suspendJMXRegistration/resumeJMXRegistration</h4>
It is sometimes useful to be able to suspend and resume registration of
gmbal-generated MBeans with the MBean server. This is mainly useful
when it is necessary to create one or more MBeans in a constructor in
order to avoid complex refactoring of the code. Normally
ManagedObjectManager.register( this ) should NOT be used in a
constructor, because it exposes a partially constructed object to the
MBean server, which may then invoke methods on the partially
constructed object in order to execute operations, or get or set
attributes. However, gmbal itself will NEVER invoke any method or
access any field of an object unless an MBean operation requires it, so
it is safe to pass partially constructed objects into gmbal itself. So
avoiding MBeanServer registration by suspending registration allows
this case to be handled easily.<br>
<br>
<h4>3.2.12. getAMXClient</h4>
This returns an AMXClient that is a convenient wrapper for accessing
the features of the MBean corresponding to the object passed to
getAMXClient.<br>
<br>
<h4>3.2.13. getDomain</h4>
This method returns the domain for all MBeans created in the mom.&nbsp;
This is either the domain passed to createStandalone, or the domain of
the ObjectName passed to createFederated.<br>
<br>
<h4>3.2.14. isManagedObject</h4>
This method is a convenience API that simply checks whether or not the
object passed to isManagedObject is annotated as a @ManagedObject or
not.<br>
<br>
<h4>3.2.15. suppressDuplicateRootReport<br>
</h4>
This controls the behavior of setting the MOM's root.&nbsp; If true, no
error is reported when the root has already been registered with the
JMX MBeanServer.&nbsp; This method was added to allow GFv3 monitoring
to avoid reporting an uninteresting error.<br>
<br>
<h2>4. Further notes on the API<br>
</h2>
There are a number of details about how the APIs work that require
further
discussion.<br>
<h3><a name="4.1._Processing_of_method_names_for_IDs"></a>4.1.
Processing of method names for IDs</h3>
The following rules are applied to generate attribute and operation IDs
from
method names:<br>
<br>
<ol>
  <li>If the method is annotated with @ManagedAttribute:<br>
    <ol>
      <li>If the method is a getter (that is, it has no arguments and a
non-void result):
        <ol>
          <li>If the method name starts with "get" or "is", remote the
prefix.&nbsp; The rest of the method name is the attribute ID for an
attribute in a ManagedObject.&nbsp; If the attribute is in a
ManagedData, then the first character is forced to lower case.<br>
          </li>
          <li>Otherwise the method name is the id.<br>
          </li>
        </ol>
      </li>
      <li>If the method is a setter (that, has one argument and a void
result):
        <ol>
          <li>If the method name starts with "set", remove "set". The
rest of the method name is the attribute ID for an attribute in a
ManagedObject.&nbsp; If the attribute is in a ManagedData, then the
first character is forced to lower case.&nbsp;</li>
          <li>Otherwise the method name is the id.</li>
        </ol>
      </li>
      <li>Otherwise the method is not a valid attribute, and an
exception will be thrown<br>
      </li>
    </ol>
  </li>
  <li>If the method is annotated with @ManagedOperation:
    <ol>
      <li>The id is the method name.</li>
    </ol>
  </li>
</ol>
These rules are applied unless the ManagedAttribute or ManagedOperation
annotation has a non-default id attribute, in which case the id from
the annotation is used.<br>
<h3><a name="4.2._I18N_support"></a>4.2. I18N support</h3>
Gmbal supports I18N by supplying a ResourceBundle to the
ManagedObjectManager.&nbsp; If this option is used, all values of
@Description annotations must be resource bundle keys.&nbsp; The
appropriate
ResourceBundle must then be associated with the ManagedObjectManager
when the ManagedObjectManager is created.<br>
<br>
Note: this feature is not implemented in the GFv3 FCS version of Gmbal.<br>
<br>
<h3><a name="4.3._OpenType_mapping_"></a>4.3. OpenType mapping<br>
</h3>
Gmbal mostly follows the OpenType mapping rules for MXBeans (see the <a
 href="http://java.sun.com/javase/6/docs/api/javax/management/MXBean.html#mapping-rules">Type
Mapping Rules</a>), but of course<br>
MXBeans are only available on JDK 6 and later, and gmbal supports JDK
5. There
are a few differences:<br>
<ol>
  <li>Gmbal supports all Collection, Iterator, Iterable, and
Enumeration types where MXBeans support List, Set, and SortedSet.</li>
  <li>Gmbal also maps Dictionary as well as Map to TabularType.</li>
  <li>Gmbal maps all @ManagedObject types to ObjectName (in MXBeans,
this is any MXBean interface).</li>
  <li>Gmbal only maps other types to CompositeData if the type has an
@ManagedData annotation.&nbsp; If not, gmbal maps the type to a String
using its toString() method.</li>
  <li>Gmbal does not support reconstructing a Java type from
CompositeData. Gmbal could be extended in this area if necessary.</li>
  <li>Gmbal will provide more support for converting generic types into
generic MBean types, which can be instantiated into specific MBeans
based on the actual type parameters supplied to an instance of the
generic type.</li>
</ol>
Gmbal does not currently provide support for setting attributes with
CompositeData values (but this would be easy to add,&nbsp; following
the rules used for MXBeans).<br>
<h3><a name="4.4._Metadata_support_"></a>4.4. Metadata support<br>
</h3>
Gmbal fully supports extensible metadata on MBeans by using the JMX
ModelMBean
Descriptor, which is available on JDK 5. JDK 6 has applied Descriptor
support to ALL MBean metadata, but gmbal must
continue to support JDK 5 for now. Gmbal supports the @DescriptorKey
and @DescriptorFields annotations defined in
JSR 255 for associating metadata with MBeans.&nbsp; Gmbal also defines
an annotation @AMXMetadata (which itself uses
the meta-annotation @DescriptorKey) in order to support the metadata
needed by AMX.<br>
<br>
@AMXMetadata can be used most easily on a simple mbean::<br>
<pre>@AMXMetadata<br>public interface MyBean1 { ... }<br></pre>
<p>In this case, MyBean1 is a singleton (only one of this type may
appear in the same parent), its MBean info never changes, the proxy
interface name defaults to a generic implementation, the group is
other, and the list of valid subtypes is empty, which means any type
may appear as a child.&nbsp; Note that
the @AMXMetadata annotation is not needed at all in this case. <br>
</p>
<p>Something like<br>
</p>
<pre>@AMXMetadata( isSingleton=false, type=Widget )<br>public interface MyBean2 { ... }<br></pre>
<p>defines an AMX MBean which is not a singleton.&nbsp; Also, the
type will be set to Widget in the ObjectName created for an instance of
MyBean2.<br>
</p>
The use of @DescriptorKey is discussed (with a good example) in the
Java 6 Javadoc for <a
 href="http://java.sun.com/javase/6/docs/api/javax/management/DescriptorKey.html">DescriptorKey</a>.
Eamonn McManus discusses @DescriptorKey and @DescriptorFields in a
rather lengthy blog post "<a
 href="http://weblogs.java.net/blog/emcmanus/archive/2007/08/defining_mbeans.html">Defining
MBeans with Annotations</a>".&nbsp; Either annotation allows
almost any sort of metadata to be added to MBeans defined by gmbal,
with no changes to gmbal required to add the additional metadata.<span
 style="font-weight: bold;"></span>
<h3>4.5. AMX support for MBeans</h3>
Gmbal is fully compliant with all requirements and recommendations
of the
<a
 href="https://glassfish.dev.java.net/nonav/v3/admin/planning/V3Changes/V3_AMX_SPI.html">GlassFish
v3 AMX SPI</a>.<br>
This includes:<br>
<ul>
  <li>Creating ObjectNames according to the parent/child
hierarchy.&nbsp; Gmbal will never put anything in an ObjectName that is
not part of the AMX specification.</li>
  <li>Supporting the MBeanInfo Descriptor.&nbsp; This is handled in
gmbal through the @AMXMetadata annotation.</li>
  <li>All MBeans created using gmbal will include all of the attributes
defined in section 4.0 "Attributes" of the AMX SPI <a
 href="https://glassfish.dev.java.net/nonav/v3/admin/planning/V3Changes/V3_AMX_SPI.html">spec</a>.</li>
  <li>Gmbal will only use Open data types for MBean attribute values
and operation arguments and results.&nbsp; But gmbal will map most Java
data types to the appropriate Open data types, following the MXBean
specification (with some differences; see "<a
 href="#4.3._OpenType_mapping_">OpenType mapping</a>").<br>
  </li>
  <li>Gmbal will support all of the behavior requirements of section 5
of the AMX SPI spec.&nbsp; This include support for
AttributeChangeNotification.<br>
  </li>
</ul>
<h3><a name="4.6._Using_Gmbal_"></a>4.6. Using Gmbal<br>
</h3>
The basic usage of Gmbal is as follows:<br>
<ol>
  <li>Add annotations to existing application objects (here application
means anything you want to manage, part of GFv3 or not) to expose
attributes and operations.</li>
  <li>In some cases you may need to expose some data by defining new
methods.&nbsp; Currently all gmbal visible annotations must be public,
but I may relax that (at the cost of requiring an access check
permission for reflection).</li>
  <li>In the initialization of a module, create an appropriate
ManagedObjectManager (call it mom).&nbsp; This requires thinking about
where in the federated hierarchy the root of the ManagedObjectManager
should live.&nbsp; In some cases, this may be different depending on
the environment in which the instrumented code runs.</li>
  <li>Whenever an Object is created that requires a management
interface, register that object with the mom.</li>
  <li>Whenever an Object is no longer needed, unregister that object
with the mom.</li>
  <li>Whenever the module lifecycle ends, call mom.close() to clean up
the root object and any other remaining registered objects.</li>
</ol>
Here is an example of typical code for using gmbal. All examples are
taken from the experimental version of the GlassFish v3 ORB
(available in the <a
 href="https://kenai.com/hg/gf-corba-v3-mirror%7Ecorba-gmbal">experimental</a>
ORB repository from the GFv3 ORB project on Kenai.com):<br>
<br>
First, from the
com.sun.corba.se.spi.orb.ORB.createORBManagedObjectManager method:<br>
<pre>    // mom is declared the ORB object, which stays around the entire time the ORB is in use.<br>    // Here I am using createStandalone.  This needs to be replaced with a call to createFederated<br>    // when running in GlassFish v3.  This will be driven through the ORB configuration.<br>    mom = ManagedObjectManagerFactory.createStandalone( "com.sun.corba" ) ;<br><br>    // The ORB already has a system for setting debug options, so I just extended it for gmbal.<br>    if (mbeanFineDebugFlag) {<br>        mom.setRegistrationDebug( ManagedObjectManager.RegistrationDebugLevel.FINE ) ;<br>    } else if (mbeanDebugFlag) {<br>        mom.setRegistrationDebug( ManagedObjectManager.RegistrationDebugLevel.NORMAL ) ;<br>    } else {<br>        mom.setRegistrationDebug( ManagedObjectManager.RegistrationDebugLevel.NONE ) ;<br>    }<br><br>    mom.setRuntimeDebug( mbeanRuntimeDebugFlag ) ;<br><br>    // Here I add all of the package prefixes that I do NOT want to see in ObjectNames.<br>    // The longest match is stripped from the class name to create the default value for the<br>    // type.<br>    mom.stripPrefix( "com.sun.corba.se" ) ;<br>    mom.stripPrefix( "com.sun.corba.se.spi" ) ;<br>    mom.stripPrefix( "com.sun.corba.se.impl" ) ;<br>    mom.stripPrefix( "com.sun.corba.se.spi.orbutil" ) ;<br>    mom.stripPrefix( "com.sun.corba.se.impl.orbutil" ) ;<br></pre>
<pre>    // Here I am using the guaranteed to be unique ORB id as the name of the topmost ORB mbean.<br>    mom.createRoot( this, getUniqueOrbId() ) ;</pre>
<p><br>
In order to integrate the ORB with GlassFish v3, there is quite a
bit of GlassFish v3-specific code that initializes the ORB. This code
will need to be placed in an appropriate OSGi bundle (either in the EJB
remote bundle, or possible in a separate embedded ORB support bundle).
Then the ORB SPI needs to be extended to support a call like
setMBeanRootParent( ObjectName ).&nbsp; If this method is called (which
would normally only happen from inside the ORB support code in
GlassFish v3), the initialization sequence needs to call
ManagedObjectManagerFactory.createFederated instead of
createStandalone.&nbsp; Everything else stays exactly the same, giving
an easy way to run the ORB either in GlassFish v3, or standalone (for
example, as part of JDK 7, if we get to that).<br>
</p>
<p>Next we need to see an example of MBean creation code.&nbsp; Again
the example is from the GFv3 ORB, this time in the timer subsystem
(from the orblibrary package com.sun.corba.se.spi.orbutil.newtimer).
The timer subsystem defines a number of different interfaces (e.g.
Timer, TimerGroup, TimerFactory, StatsEventHandler among others),
instances of which are registered as MBeans. Each of these classes
extends a base interface called Named defined as follows:<br>
</p>
<pre>public interface Named {<br>    /** Return the TimerFactory that created this Named.<br>     */<br>    @ManagedAttribute<br>    @Description( "TimerFactory that created this Timer or TimerGroup" ) <br>    TimerFactory factory() ;<br><br>    /** A short name for this Controllable.<br>     */<br>    @ManagedAttribute<br>    @NameValue<br>    @Description( "Name of this Timer or TimerGroup" ) <br>    String name() ;<br>}<br></pre>
<p>Note that the name() attribute carries the @NameValue
attribute.&nbsp; This simplifies the registration which takes place in
TimerFactoryImpl.&nbsp; The TimerFactoryImpl contains all of the
factory methods for creating the various timer interfaces mentioned
previously. TimerFactoryImpl defines several private methods as follows:<br>
</p>
<pre>    private void manage( Named obj ) {<br>        // Note that no extra parameters are needed here, because Named.getName<br>        // is an NameValue.<br>        if (mom != null)  {<br>            // System.out.println( "Registering " + obj ) ;<br>            mom.registerAtRoot( obj ) ;<br>        }<br>    }<br><br>    private void manage( Named parent, Named obj ) {<br>        // Note that no extra parameters are needed here, because Named.getName<br>        // is an NameValue.<br>        if (mom != null)  {<br>            // System.out.println( "Registering " + obj ) ;<br>            mom.register( parent, obj ) ;<br>        }<br>    }<br><br>    private void unmanage( Named obj ) {<br>        if (mom != null) <br>            mom.unregister( obj ) ;<br>    }<br></pre>
<p>These methods support the case where no ManagedObjectManager (mom)
is present, which may be a useful pattern in other cases. For example,
Grizzly must be able to run in as small a configuration as possible,
but Grizzly would like to have MBeans available as an option.
Consequently, the gmbal annotations and API (plus one small utility
class) are defined in the gmbal-api-only <a href="#7._Project_Details">bundle</a>
(about 14K).&nbsp; Another bundle (gmbal, about 240K) includes
everything in gmbal-api-only, plus a full implementation.&nbsp;
One&nbsp; of the bundles gmbal-api-only or gmbal needs to be present in
all cases, and all
of the code in this example requires ONLY gmbal-api-only.&nbsp; If <a
 href="#7._Project_Details">gmbal</a> is NOT
available, ManagedObjectManagerFactory.<a href="#3.1.2._create">createStandalone</a>
and <a href="#3.1.2._create">createFederated</a> will return an
instance of a no-op implementation of ManagedObjectManager. This would
allow the above code to avoid the null check, which was required in an
older version of gmbal.<br>
</p>
<p>Now consider actually creating instances of various timer classes.
FIrst, the TimerManager is itself represented by an MBean, so it must
be registered. It is tempting to do this in the constructor (in fact,
this mistake has been made in the ORB). <span
 style="font-weight: bold;">You should not do this!</span>&nbsp;
Calling mom.<a href="#3.2.3._register_and_registerAtRoot">register</a>(
this ) in the constructor violates one of the cardinal rules of Java
concurrent programming: do not publish objects before construction is
complete.&nbsp; As soon as the mom.register call returns, the MBean has
been registered with the ManagedObjectManager's MBeanServer, and this
means that remove invocations on unknown thread could arrive at any
moment, <span style="font-weight: bold;">including before the
constructor has returned</span>. Note that any method of an object that
is used at an attribute or operation <span style="font-weight: bold;">MUST
</span>be thread safe, as such a method can be invoked at any by one or
more threads from remote JMX connectors.<br>
</p>
<p>However, there are times when the constructor is the only reasonable
place to do the registration. This happen in situations where:<br>
</p>
<ul>
  <li>There is a top-level constructor that initializes a large
hierarchy of objects.</li>
  <li>The top-level constructor needs to create the
ManagedObjectManager and root before it initializes the other objects
that need a ManagedObjectManager.</li>
  <li>Since creating the root registers an MBean, we don't normally
want to do this in the constructor</li>
</ul>
To avoid this problem, the ManagedObjectManager now supports
suspend/resume on registration of MBeans with the MBeanServer through
the methods suspendJMXRegistration() and resumeJMXRegistration(). When
registration is suspended, newly created MBeanImpl instances are kept
in a queue.&nbsp; Once resume is called, all enqueued MBeanImpl
instances are registered with the MBeanServer.<br>
<p>In the timer library case, the TimerFactory is constructed by a
TimerFactoryBuilder as follows:<br>
</p>
<pre>    public synchronized static TimerFactory make( ManagedObjectManager mom, <br>        String name, String description ) {<br><br>	if (fmap.get( name ) != null)<br>	    throw new IllegalArgumentException(<br>		"There is currently a TimerFactory named " + name ) ;<br><br>	TimerFactory result = new TimerFactoryImpl( mom, name, description ) ;<br>	fmap.put( name, result ) ;<br>        <span
 style="font-weight: bold; font-style: italic;">mom.register( result ) ; // registered AFTER construction as a child of mom's root</span><br>	return result ;<br>    }<br><br></pre>
<p>Here's an example of registering a TimerGroup (from TimerFactory):<br>
</p>
<pre>    public synchronized TimerGroup makeTimerGroup( String name, <br>	String description ) {<br><br>	checkArgs( timerGroups.keySet(), name, description ) ;<br><br>	TimerGroupImpl result = new TimerGroupImpl( nextIndex, this, name, <br>	    description ) ;<br>       <span
 style="font-style: italic;"> </span><span
 style="font-weight: bold; font-style: italic;">manage( this, result ) ;</span><br><br>	mapId( result ) ;<br>	timerGroups.put( result.name(), result ) ;<br>	add( result ) ;  // Remember, a TimerFactory is a TimerGroup <br>			 // containing all<br>		         // Controllables that it creates!<br><br>	return result ;<br>    }<br></pre>
<p>Here the TimerGroup has an MBean that is registered as a child of
the TimerFactory. The TimerGroup interface itself is annotated as
follows:<br>
</p>
<pre>@ManagedObject<br>@Description( "A group of Timers or other TimerGroups, which may be enabled or disabled together" ) <br>public interface TimerGroup extends Controllable {<br>    @ManagedOperation<br>    @Description( "Add a new Timer or TimerGroup to this TimerGroup" ) <br>    boolean add( Controllable con ) ;<br><br>    @ManagedOperation<br>    @Description( "Remove a new Timer or TimerGroup from this TimerGroup" ) <br>    boolean remove( Controllable con ) ;<br>}<br></pre>
<p>Controllable is fairly complex, and defines a number of attributes:<br>
</p>
<pre>@ManagedObject<br>@IncludeSubclass( { Timer.class, TimerGroup.class, TimerFactory.class } ) <br>public interface Controllable extends Named {<br>&nbsp;&nbsp;&nbsp; /** A longer description giving some details of the meaning of this<br>&nbsp;&nbsp;&nbsp;&nbsp; * Controllable.<br>&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp; @ManagedAttribute<br>&nbsp;&nbsp;&nbsp; @Description( "The purpose of the Timer or TimerGroup" ) <br>&nbsp;&nbsp;&nbsp; String description() ;<br><br>&nbsp;&nbsp;&nbsp; /** A small id for this controllable.&nbsp; Each controllable created from<br>&nbsp;&nbsp;&nbsp;&nbsp; * the same TimerFactory will have a unique ID.&nbsp; All ids will be small<br>&nbsp;&nbsp;&nbsp;&nbsp; * integers starting at 0 (so indexing tables by timer ID is supported).<br>&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp; @ManagedAttribute<br>&nbsp;&nbsp;&nbsp; @Description( "An internal identifier for the Timer or TimerGroup" ) <br>&nbsp;&nbsp;&nbsp; int id() ;objectClass<br><br>&nbsp;&nbsp;&nbsp; /** Return an unmodifiable set of the contents of this Controllable.<br>&nbsp;&nbsp;&nbsp;&nbsp; * May always be empty for some subclasses of Controllable.<br>&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp; @ManagedAttribute<br>&nbsp;&nbsp;&nbsp; @Description( "Set of Timers or TimerGroups contained in a TimerGroup" )<br>&nbsp;&nbsp;&nbsp; Set&lt;? extends Controllable&gt; contents() ;<br><br>&nbsp;&nbsp;&nbsp; /** Enable this controllable.&nbsp; All Timers that are either enabled, or<br>&nbsp;&nbsp;&nbsp;&nbsp; * reachable via contents() from an enabled Controllable are activated,<br>&nbsp;&nbsp;&nbsp;&nbsp; * and will cause TimerEvents to be generated when passed to the<br>&nbsp;&nbsp;&nbsp;&nbsp; * TimerEventController enter and exit methods.<br>&nbsp;&nbsp;&nbsp;&nbsp; */ <br>&nbsp;&nbsp;&nbsp; @ManagedOperation<br>&nbsp;&nbsp;&nbsp; @Description( "Enable this Timer, or all Timers and TimerGroups contained in this TimerGroup" ) <br>&nbsp;&nbsp;&nbsp; void enable() ;<br><br>&nbsp;&nbsp;&nbsp; /** Disable this controllable.<br>&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp; @ManagedOperation<br>&nbsp;&nbsp;&nbsp; @Description( "Disable this Timer, or all Timers and TimerGroups contained in this TimerGroup" ) <br>&nbsp;&nbsp;&nbsp; void disable() ;<br><br>&nbsp;&nbsp;&nbsp; /** Return true if enable() was called, otherwise false if enable() was never<br>&nbsp;&nbsp;&nbsp;&nbsp; * called, or disable() was last called.<br>&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp; @ManagedOperation<br>&nbsp;&nbsp;&nbsp; @Description( "True if this Timer or TimerGroup is enabled" ) <br>&nbsp;&nbsp;&nbsp; boolean isEnabled() ;<br>}<br></pre>
<p>Because TimerGroup extends Controllable extends Named, the
TimerGroup inherits the name() attribute which is annotated with
@NameValue. This means that the result of calling timerGroup.name()
is used as the value of the name attribute in the ObjectName for the
MBean constructed for timerGroup.<br>
</p>
<p>Finally, when an object is no longer needed, the
ManagedObjectManager.<a href="#3.2.4._unregister">unregister</a> method
must be called. In some case this is handled through an explicit method
to
remove the object, e.g. for TimerEventHandle in the
TimerFactory.removeTimerEventHandler method:<br>
</p>
<pre>    public synchronized void removeTimerEventHandler( <br>	TimerEventHandler handler ) {<br><br>	timerEventHandlers.remove( handler.name() ) ;<br>        unmanage( handler ) ;<br>    }<br></pre>
<p>If the mbeans should be registered as long as the module exists,
ManagedObjectManager.<a href="#3.2.10._Close">close</a>() can be used
to unregister everything. In the case of the ORB, the close call should
happen in the ORB.destroy code.&nbsp; <br>
</p>
<h3><a name="4.7._Handling_Polymorphism"></a>4.7. Handling Polymorphism</h3>
There are cases where an attribute has a type defined by a base class
or
interface, but the actual implementation can be one of several
different classes.&nbsp; For example, the ORB has a TaggedComponent
interface, representing part of the data in a remote reference, and
there are several concrete subclasses of TaggedComponent
that are used.&nbsp; This is not a problem for @ManagedObject classes,
since they are reference by ObjectNames, and an
ObjectName can reference any type of&nbsp; MBean.&nbsp; But this does
not work for @ManagedData, because @ManagedData is
mapped to a CompositeData type, and CompositeData does not support
polymorphism.<br>
<br>
Gmbal supports a limit form of polymorphism to handle this case using
the
@IncludeSubclass annotation.&nbsp; @IncludeSubclass gives the
subclasses of a @ManagedData type which themselves can contribute
attributes to the CompositeData for the parent class.&nbsp; Gmbal
generates a CompositeData type that contains the union of
all fields in all of the subclasses. At runtime, only those attributes
actually present in a particular instance of the
@ManagedData class are present in the CompositeData for the
instance.&nbsp; In this way, gmbal supports a limit form of
polymorphism under a closed-world assumption.<br>
<br>
Here is an example from the CORBA case:<br>
<br>
first, the base interface:<br>
<pre>/** Generic interface for all tagged components.  Users of the ORB may<br>* create implementations of this class and also corresponding factories<br>* of type TaggedComponentFactory.  The factories can be registered with an<br>* ORB instance, in which case they will be used to unmarshal IORs containing<br>* the registered tagged component.<br>*/<br>@ManagedData<br>@Description( "Base class for all TaggedComponents" )<br>@IncludeSubclass( { AlternateIIOPAddressComponent.class, <br>    CodeSetsComponent.class, JavaCodebaseComponent.class,<br>    MaxStreamFormatVersionComponent.class, ORBTypeComponent.class,<br>    RequestPartitioningComponent.class,<br>    GenericTaggedComponent.class } )<br>public interface TaggedComponent extends Identifiable<br>{<br>    org.omg.IOP.TaggedComponent getIOPComponent( ORB orb ) ;<br>}<br></pre>
<p>then, an example of two of the subclasses:<br>
</p>
<pre>@ManagedData<br>@Description( "Component containing an alternate IIOP address to use" )<br>public interface AlternateIIOPAddressComponent extends TaggedComponent<br>{<br>    @ManagedAttribute<br>    @Description( "The Alternate address" ) <br>    public IIOPAddress getAddress() ;<br>}<br><br>@ManagedData<br>@Description( "Component representing Codebase URLs for downloading code" )<br>public interface JavaCodebaseComponent extends TaggedComponent <br>{<br>    @ManagedAttribute<br>    @Description( "List of URLs in the codebase" ) <br>    public String getURLs() ;<br>}<br></pre>
<p>The result of this is that any reference to the TaggedComponent type
in a @ManagedObject will mapped to CompositeData with the Address and
URLs attributes.&nbsp; However, the actual CompositeData to which an
instance of TaggedComponent is mapped will only have Address if it isA
AlternateIIOPAddressComponent, otherwise that attribute will be
unavailable.&nbsp; If TaggedComponent defined any attributes, those
attributes would be present in all instance of CompositeData
representing a TaggedComponent (in this case the
org.omg.IOP.TaggedComponent type is simply not interesting enough to
expose as an Attribute).<br>
</p>
<h3><a name="L2005" id="L2005"></a>4.8. Issues with generic types</h3>
<p>This is best explained with an example.&nbsp; Suppose we have
interfaces defined
as follows:<br>
</p>
<pre>@ManagedData<br>public interface ExampleData&lt;S,T&gt; {<br>    S       getInfo() ;<br><br>    List&lt;T&gt; getData() ;<br>}<br><br>public interface Example&lt;S,T&gt; {<br>    @ManagedAttribute<br>    ExampleData&lt;S,T&gt; getInfo() ;<br>}<br><br>@ManagedObject<br>public interface MyBean extends Example&lt;Date,List&lt;String&gt;&gt; {<br>}<br></pre>
What sort of MBean should we create for MyBean?&nbsp; If we just use
reflection on
MyBean, we find an attribute info that returns an
ExampleData&lt;S,T&gt;, which would turn into a CompositeData with
two attributes:<br>
<ul>
  <li>id=info, type=Object (since type is type variable S)</li>
  <li>id=data, type=Object (since type is type variable T)<br>
  </li>
</ul>
But we actually have a lot more information than this: if we "evaluate"
the
types, we see that MyBean extends
Example&lt;Data,List&lt;String&gt;&gt;, so the Example.getInfo method
has type MethodData&lt;Date,List&lt;String&gt;&gt;, and so
MyBean.getInfo returns a composite data with 2 attributes:<br>
<ul>
  <li>id=info, type=Date</li>
  <li>id=data, type=List&lt;List&lt;String&gt;&gt;</li>
</ul>
So instead of erasing the types, we evaluate the type variable by
replacing the
type variables with the types used to instantiate them.&nbsp; Another
way of looking at this is that annotating a
generic interface or class with @ManagedData or @ManagedObject is
basically creating a template for creating the actual
CompositeData or Open MBean.<br>
<h3>4.9. Issues with recursive types</h3>
CompositeData cannot be defined directly from class definitions that
have
recursive types.&nbsp; Here is an example of the problem:<br>
<pre>@ManagedData<br>public interface A {<br>    @ManagedAttribute<br>    B getB() ;<br>}<br><br>@ManagedData<br>public interface B {<br>    @ManagedAttribute<br>    A getA() ;<br>}<br></pre>
The problem here is that we need to construct an instance of
CompositeType to
represent the OpenType to which A and B are&nbsp; mapped.&nbsp; But
CompositeData is immutable, so in order to construct the
CompositeType for A, we need the CompositeType of B, which can't be
constructed without using the CompositeType of A.&nbsp; So a
direct mapping fails here, and gmbal will detect this problem and throw
an exception.<br>
<br>
The way to work around the problem is to add a level of indirection so
that one
of the classes refers to the other indirectly. For example, support A
has a convenient String name attribute we can use (which
is a key for instances of A).&nbsp; Then the above can be expressed as:<br>
<pre>@ManagedData <br>public interface A {<br>    @ManagedAttribute<br>    String getName() ;<br><br>    @ManagedAttribute<br>    B getB() ;<br>}<br><br>@ManagedData<br>public interface B {<br>    @ManagedAttribute( id="A" ) <br>    String getARef() ; // returns getA().getName()<br><br>    A getA() ;<br>}<br></pre>
In this way the relationship between A and B can still be represented
in the
management API without needing recursive references between different
data types that are represented with
CompositeData.<br>
<br>
Note that it is possible to automate this to some extent, but I
currently have
no plans to extend gmbal to automatically handle this problem.<br>
<h3>4.10 Method call order requirements</h3>
As noted in the methods on the ManagedObjectManager, there are
constraints on the order in which certain methods may be called. This
is done to avoid problems where some MBeans are created, then other
methods are called (like addAnnotation or stripPrefix) which could
change the attributes, operations, ObjectNames, or metadata on any
Gmbal MBean that has already been created.&nbsp; This divides the
methods up into 3 categories:<br>
<ul>
  <li>Methods that can only be called before the first successful call
to a createRoot method: <br>
  </li>
  <ul>
    <li>the 3 createRoot methods<br>
    </li>
    <li>stripPrefix</li>
    <li>stripPackagePrefix</li>
    <li>setResourceBundle</li>
    <li>setMBeanServer<br>
    </li>
    <li>addAnnotation</li>
  </ul>
  <li>Methods that can only be called after the first successful call
to a createRoot method:</li>
  <ul>
    <li>The 2 register methods</li>
    <li>The 2 registerAtRoot methods</li>
  </ul>
  <ul>
    <li>unregister</li>
    <li>getRoot</li>
    <li>getObject</li>
    <li>getObjectName<br>
    </li>
  </ul>
  <li>Methods that can be called at any time:</li>
  <ul>
    <li>getResourceBundle</li>
    <li>getMBeanServer</li>
    <li>getDomain<br>
    </li>
    <li>suspendJMXRegistration</li>
    <li>resumeJMXRegistration</li>
    <li>setRuntimeDebug</li>
    <li>setRegistrationDebug</li>
    <li>setTypelibDebug<br>
    </li>
  </ul>
</ul>
Any violation of this requirement results in an IllegalStateException.<br>
<h3>4.11. Computing the type name</h3>
The type name used in the ObjectName is computed as follows from the
class of the registered object:<br>
<ol>
  <li>If the class contains a final static field of type String name
AMX_TYPE, the value of the field is the type.</li>
  <li>Otherwise, if the class has an annotation @AMXMetadata and the
type field is not "", the type field is the type.</li>
  <li>Otherwise, if the package prefix of the class name matches one of
the stripPrefix call arguments, that part of the package prefix is
removed from the full class name, and the remainder (minus the initial
dot) is the type name.</li>
  <li>Otherwise, if stripPackagePrefix was called, the entire package
prefix is removed (if any), and the remaining class name is the type
name.</li>
  <li>Otherwise, the full class name is the type name.</li>
</ol>
The same algorithm is used for determining the name of a CompositeData
type for @ManagedData, with a few slight differences:<br>
<ol>
  <li>If the class contains a final static field of type String name
GMBAL_TYPE, the value of the field is the name.</li>
  <li>Otherwise, if the class's @ManagedData annotation has a name
element with a value other than "", the value of the name element is
the name.</li>
  <li>Otherwise, if the package prefix of the class name matches one of
the stripPrefix call arguments, that part of the package prefix is
removed from the full class name, and the remainder (minus the initial
dot) is the name.</li>
  <li>Otherwise, if stripPackagePrefix was called, the entire package
prefix is removed (if any), and the remaining class name is the type
name.</li>
  <li>Otherwise, the full class name is the name.</li>
</ol>
<h2>5. Dependencies</h2>
The only dependency that gmbal has is JDK 5.&nbsp; It does not require
anything
from JMX that is not in JDK 5.&nbsp; It also has no ant<br>
&nbsp;dependencies on
GlassFish v3&nbsp; or
CORBA.<br>
<h2>6. Testing</h2>
All tests for gmbal are written in Java using JUnit, and reside in the
test
directory in the project.<br>
<br>
The following tests are currently available:<br>
<br>
<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
 cellspacing="2">
  <tbody>
    <tr>
      <td style="vertical-align: top;"><span style="font-weight: bold;">Test
Package Name</span><br>
      </td>
      <td style="vertical-align: top;"><span style="font-weight: bold;">Tests
Included</span><br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal<br>
      </td>
      <td style="vertical-align: top;">ManagedObjectManager and basic
annotation processing<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal.generic<br>
      </td>
      <td style="vertical-align: top;">Facet mechanism used for dynamic
inheritance<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal.impl<br>
      </td>
      <td style="vertical-align: top;">TypeConverter test<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal.logex<br>
      </td>
      <td style="vertical-align: top;">Testing the log wrapper generator<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal.typelib<br>
      </td>
      <td style="vertical-align: top;">Tests the typelib (derived from
a JDK 7 test suite)<br>
      </td>
    </tr>
  </tbody>
</table>
<br>
<h2><a name="7._Project_Details"></a>7. Project Details</h2>
The gmbal project is available in a mercurial workspace at <a
 href="https://kenai.com/hg/gmbal%7Emaster">https://kenai.com/hg/gmbal~master.</a>&nbsp;
Note that gmbal will
NOT be built as part of the&nbsp; GFv3 build.&nbsp; This is
necessary because gmbal is also used outside of GFv3, and we need to
avoid
circular build dependencies (e.g. GFv3 dependsOn CORBA dependsOn gmbal,
which
creates a build loop if GFv3 also contains gmbal).<br>
<br>
gmbal uses the following Java packages:<br>
<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
 cellspacing="2">
  <tbody>
    <tr>
      <td style="vertical-align: top;"><span style="font-weight: bold;">Package
Name</span><br>
      </td>
      <td style="vertical-align: top;"><span style="font-weight: bold;">OSGi&nbsp;
Bundle</span><br>
      </td>
      <td style="vertical-align: top;"><span style="font-weight: bold;">Purpose</span><br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal<br>
      </td>
      <td style="vertical-align: top;">gmbal-api-only, gmbal<br>
      </td>
      <td style="vertical-align: top;">all public interfaces<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal.util<br>
      </td>
      <td style="vertical-align: top;">gmbal-api-only, gmbal<br>
      </td>
      <td style="vertical-align: top;">contains code needed to support
the API-Impl split (reflective construction of the implementation)<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal.generic<br>
      </td>
      <td style="vertical-align: top;">gmbal<br>
      </td>
      <td style="vertical-align: top;">General-purpose code for
debugging, plus simple function programming support<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal.impl<br>
      </td>
      <td style="vertical-align: top;">gmbal<br>
      </td>
      <td style="vertical-align: top;">The full implementation.&nbsp; <br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal.logex<br>
      </td>
      <td style="vertical-align: top;">gmbal<br>
      </td>
      <td style="vertical-align: top;">Log wrapper code for logging
exceptions and managing other I18N data<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal.tools.argparser<br>
      </td>
      <td style="vertical-align: top;">build only<br>
      </td>
      <td style="vertical-align: top;">argument parser used in
copyright utilities (from CORBA)<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal.tools.file<br>
      </td>
      <td style="vertical-align: top;">build only<br>
      </td>
      <td style="vertical-align: top;">file handling utilities and
copyright process (from CORBA)<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">org.glassfish.gmbal.typelib<br>
      </td>
      <td style="vertical-align: top;">gmbal<br>
      </td>
      <td style="vertical-align: top;">utility library for type
evaluation<br>
      </td>
    </tr>
  </tbody>
</table>
<br>
The gmbal project also contains the package
org.glassfish.probe.provider.annotations, which is present in gmbal so
that projects that are not part of GFv3 may support GlassFish
monitoring probes without depending at build-time or runtime on
anything other than a single probe bundle.<br>
<br>
The resulting OSGi bundles are currently (version 3.0-FCS) sized at:<br>
<br>
<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
 cellspacing="2">
  <tbody>
    <tr>
      <td style="vertical-align: top;">gmbal-api-only<br>
      </td>
      <td style="vertical-align: top;">22 KBytes<br>
      </td>
    </tr>
    <tr>
      <td style="vertical-align: top;">gmbal<br>
      </td>
      <td style="vertical-align: top;">272 Kbytes<br>
      </td>
    </tr>
  </tbody>
</table>
<br>
Any gmbal client needs to use either gmbal-api-only or gmbal, but not
both.&nbsp; Both bundles are available in the standard place in the
maven repository, with group ID org.glassfish.gmbal.<br>
<br>
The probe annotations are in the gfprobe-provider-client bundle, which
is currently 2576 bytes.
<br>
Source bundles are also provided for both gmbal (gmbal-source) and
grprobe-provider-client (gfprobe-provider-client-source).
</body>
</html>