Ken Cavanaugh - The Gmbal project
Ken Cavanaugh - The Gmbal project
Ken Cavanaugh - The Gmbal project
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>Gmbal</strong><br />
Sustaining TOI<br />
<strong>Ken</strong> <strong>Cavanaugh</strong><br />
Friday, December 11, 2009<br />
1
Outline<br />
MBeans<br />
AMX<br />
Review of <strong>Gmbal</strong> API<br />
Use in GF and CORBA<br />
Build and release details<br />
Implementation packages and overview<br />
Debugging tips<br />
Current tests<br />
Friday, December 11, 2009<br />
2
MBeans<br />
Management interface defined in JMX<br />
<strong>Gmbal</strong> is a convenient way to create MBeans<br />
<strong>Gmbal</strong> creates MBeans that are:<br />
Open MBeans (dynamic MBeans with Open data)<br />
AMX compliant<br />
Have Model MBean metadata<br />
Are JDK 5 compliant<br />
JDK 6 has significant JMX changes<br />
Still supporting JDK 5 while <strong>Gmbal</strong>’s customers require it<br />
Friday, December 11, 2009<br />
3
AMX<br />
AMX MBeans are GlassFish v3’s version of MBeans<br />
AMX is an interface specification: <strong>Gmbal</strong> is an implementation of AMX<br />
AMX requirements:<br />
ObjectNames have a very specific form that defines a parent/child<br />
hierarchy<br />
A number of required attributes for metadata<br />
Several required MBean attributes:<br />
Parent<br />
Name<br />
Children<br />
Friday, December 11, 2009<br />
4
<strong>Gmbal</strong> API: Annotations<br />
8 basic annotations:<br />
@ManagedObject and @ManagedData<br />
@ManagedAttribute<br />
@ManagedOperation and @ParameterNames<br />
@NameValue<br />
@Description<br />
@AMXMetadata<br />
5 specialized annotations:<br />
@InheritedAttribute and @InheritedAttributes<br />
@IncludeSubclass<br />
@DescriptorKey and @DescriptorFIelds<br />
Friday, December 11, 2009<br />
5
<strong>Gmbal</strong> API: Interface and Factory<br />
One interface (ManagedObjectManager) that handles registration and<br />
related operations.<br />
One concrete class (ManagedObjectManagerFactory) to obtain<br />
ManagedObjectManagers.<br />
Friday, December 11, 2009<br />
6
ManagedObjectManager API:<br />
registration<br />
public interface ManagedObjectManager {<br />
NotificationEmitter getRoot() ;<br />
NotificationEmitter createRoot() ;<br />
NotificationEmitter createRoot( Object obj ) ;<br />
NotificationEmitter createRoot( Object obj, String name ) ;<br />
NotificationEmitter register( Object obj ) ;<br />
NotificationEmitter registerAtRoot( Object obj ) ;<br />
NotificationEmitter registerAtRoot( Object obj, String name ) ;<br />
NotificationEmitter register( Object parent, Object obj ) ;<br />
NotificationEmitter register( Object parent, Object obj, String name ) ;<br />
void unregister( Object obj ) ;<br />
}<br />
• Each MOM must have 1 root<br />
• Unregister when needed<br />
• Name required unless object has @NameValue method<br />
Friday, December 11, 2009<br />
7
Deferred and Suspended<br />
Registration<br />
Registration with the MBean server does not alway happen<br />
immediately<br />
MOM has a suspend/resume API to allow program to defer<br />
registration until some later point (usually after all init has completed)<br />
Problem: as soon as an MBean is registered, it can (and will!) be<br />
called asynchronously (AMX validator always runs)<br />
Can suspend before any MBeans created, then resume after all init<br />
completes<br />
MOM created by createFederated may have deferred registration<br />
Can’t create MOM root until root parent exists (AMX requirement)<br />
Transparent to <strong>Gmbal</strong> client in most ways<br />
Note that AMX is NOT started in GFv3 by default<br />
All of this is handled in the JMXRegistrationManager<br />
Friday, December 11, 2009<br />
8
ManagedObjectManager API:<br />
miscellaneous<br />
public interface ManagedObjectManager {<br />
void suspendJMXRegistration() ;<br />
void resumeJMXRegistration() ;<br />
ObjectName getObjectName( Object obj ) ;<br />
Object getObject( ObjectName oname ) ;<br />
void stripPrefix( String... str )<br />
String getDomain() ;<br />
MBeanServer getMBeanServer() ;<br />
void setMBeanServer( MBeanServer server ) ;<br />
ResourceBundle getResourceBundle() ;<br />
void setResourceBundle( ResourceBundle rb ) ;<br />
void addAnnotation( AnnotatedElement element, Annotation annotation )<br />
}<br />
Suspend/resume to deal with registration in constructor problem<br />
Access object name object mapping for registered objects<br />
set/get MBeanServer and description resource bundle<br />
stripPrefix and addAnnotations discussed later<br />
Friday, December 11, 2009<br />
9
ManagedObjectManager API:<br />
Debugging<br />
interface ManagedObjectManager {<br />
public enum RegistrationDebugLevel { NONE, NORMAL, FINE } ;<br />
void setRegistrationDebugLevel( RegistrationDebugLevel level ) ;<br />
}<br />
void setRuntimeDebug( boolean flag ) ;<br />
void setTypelibDebug( int level ) ;<br />
void setJMXRegistrationDebug( boolean flag ) ;<br />
String dumpSkeleton( Object obj ) ;<br />
void suppressDuplicateRootReport( boolean suppressReport ) ;<br />
Several different tracing capabilities<br />
Tracing when MBeans are constructed<br />
FINE adds<br />
Tracing when MBean methods are invoked<br />
Tracing for type evaluation in typelib<br />
Tracing for registration of MBean with JMX<br />
Dump the skeleton for any registered object<br />
Control reporting of duplicate setRoot calls<br />
Friday, December 11, 2009<br />
10
ManagedObjectManagerFactory<br />
public final class ManagedObjectManagerFactory {<br />
public static ManagedObjectManager createStandalone( String domain ) { ... }<br />
}<br />
public static ManagedObjectManager createFederated( ObjectName rootParentName ) { ... }<br />
• Only concrete class in the API<br />
• createStandalone(String) takes a domain used in all ObjectNames from<br />
this ManagedObjectManager.<br />
• Typically used in standalone case<br />
• createFederated(rootParentName) takes an AMX-compliant ObjectName<br />
which is the parent of the ManagedObjectManager’s root<br />
• Typically used in GFv3 case<br />
Friday, December 11, 2009<br />
11
Use of <strong>Gmbal</strong><br />
In GlassFish v3<br />
Annotations used along with GF probes<br />
Used to create MBeans for GF monitoring<br />
In CORBA<br />
Create MBeans directly for management API<br />
ORB MBean Hierarchy:<br />
gmbal root (amx parent in GlassFish)<br />
various internal APIs are available as MBean<br />
I’ll talk about this more in the CORBA TOI<br />
Lloyd will talk about tools for viewing AMX MBeans in GFv3<br />
Friday, December 11, 2009<br />
12
Workspace and Artifacts<br />
Project is at http://kenai.com/<strong>project</strong>s/gmbal<br />
Currently master is the gmbal repository at http://kenai.com/hg/<br />
gmbal~master (tag is VERSION-3.0.0-b023)<br />
Artifacts are all available in Maven at http://download.java.net/<br />
maven/2/org/glassfish/gmbal<br />
Current valid artifacts:<br />
Group ID Artifact ID Current Version<br />
(in GF 3.0-FCS)<br />
org.glassfish.gmbal gmbal-api-only 3.0.0-b023<br />
org.glassfish.gmbal gmbal-api-only-source 3.0.0-b023<br />
org.glassfish.gmbal gmbal 3.0.0-b023<br />
org.glassfish.gmbal gmbal-source 3.0.0-b023<br />
Friday, December 11, 2009<br />
13
Build and Integration Process<br />
Make a clone of the repository at https://hg.kenai.com/hg/<br />
gmbal~master<br />
use -r option for a specific version (e.g. -r 3.0-FCS)<br />
hg tags command will display all versions<br />
Build with “ant all”<br />
To make a new release:<br />
edit build.properties<br />
change build.int to the new build version<br />
or if necessary the other gmbal.* properties for different versions<br />
hg commit/hg tag /hg push<br />
“ant release” to release to maven repository<br />
Friday, December 11, 2009<br />
14
<strong>Gmbal</strong> Implementation: Packages<br />
<strong>Gmbal</strong> API:<br />
org.glassfish.gmbal<br />
org.glassfish.gmbal.util<br />
<strong>Gmbal</strong> impl:<br />
org.glassfish.gmbal.generic<br />
org.glassfish.gmbal.logex<br />
org.glassfish.gmbal.typelib<br />
org.glassfish.gmbal.impl<br />
Tools and test support:<br />
org.glassfish.gmbal.tools.argparser<br />
org.glassfisdh.gmbal.tools.file<br />
org.glassfish.gmbal.main<br />
Friday, December 11, 2009<br />
15
<strong>Gmbal</strong> API packages<br />
org.glassfish.gmbal<br />
previously discussed annotations<br />
previously discussed ManagedObjectManager and<br />
ManagedObjectManagerFactory<br />
org.glassfish.gmbal.util<br />
Contains GenericConstructor<br />
GenericConstructor( final Class type, String className,<br />
final Class... signature )<br />
T create( Object... args )<br />
ManagedObjectManagerFactory creates instances of<br />
GenericConstructor for the createFederated and createStandalone<br />
method in ManagedObjectManagerImpl<br />
Decouples interface from implementation<br />
gmbal-api-only has just the org.glassfish.gmbal and<br />
org.glassfish.gmbal.util package<br />
Friday, December 11, 2009<br />
16
org.glassfish.gmbal.generic<br />
Provides interfaces that represent functions<br />
Also algorithms that operate on functions (things like map, fold,<br />
find)<br />
Provides debugging facilities<br />
DprintUtil for method tracing<br />
OperationTracer for gathering context information for exceptions<br />
MethodMonitor to tie this together<br />
Facet accessor to provide limited dynamic inheritance<br />
Construct MBean with standard AMX attributes and application<br />
specific attributes<br />
Generic support for printing out arbitrary objects<br />
Uses annotations to control printing behavior<br />
Friday, December 11, 2009<br />
17
org.glassfish.gmbal.logex<br />
Uses an annotated interface to generate exceptions and log messages<br />
Also supports I18N for messages<br />
Example:<br />
@ExceptionWrapper( idPrefix="GMBALTLIB", resourceBundle = "org.glassfish.gmbal.logex.LogStrings" )<br />
public interface Exceptions {<br />
static final Exceptions self = WrapperGenerator.makeWrapper( Exceptions.class ) ;<br />
// Allow 100 exceptions per class<br />
static final int EXCEPTIONS_PER_CLASS = 100 ;<br />
// TypeEvaluator<br />
static final int TYPE_EVALUATOR_START = 1 ;<br />
@Message( "Internal error in TypeEvaluator" )<br />
@Log( id=TYPE_EVALUATOR_START + 0 )<br />
IllegalStateException internalTypeEvaluatorError( @Chain Exception exc ) ;<br />
}<br />
@Message( "evaluateType should not be called with a Method ({0})" )<br />
@Log( id=TYPE_EVALUATOR_START + 1 )<br />
IllegalArgumentException evaluateTypeCalledWithMethod( Object type ) ;<br />
Friday, December 11, 2009<br />
18
org.glassfish.gmbal.typelib<br />
Converts the standard java Class/java.lang.reflect.Type hierarchy into<br />
an internal form for <strong>Gmbal</strong>.<br />
Main interfaces:<br />
EvaluatedType (parent)<br />
EvaluatedDeclaration (types that can have annotations)<br />
EvaluatedFieldDeclaration<br />
EvaluatedMethodDeclaration<br />
EvaluatedClassDeclaration<br />
EvaluatedArrayType<br />
TypeEvaluator<br />
Main implementation class<br />
Provides public static EvaluatedType<br />
getEvaluatedType( Class ) method<br />
No need for Java’s type variables and wildcard types: these are<br />
evaluated out of the result (which is the whole reason for doing this)<br />
Friday, December 11, 2009<br />
19
org.glassfish.gmbal.typelib<br />
Evaluated generic types (replaces type variables with types) so that<br />
<strong>Gmbal</strong> can easily use type information to generate open types<br />
Example:<br />
@ManagedData<br />
public interface Bar {<br />
@ManagedAttribute<br />
String getName() ;<br />
}<br />
@ManagedAttribute<br />
String getAddress() ;<br />
@ManagedData<br />
public interface Foo {<br />
@ManagedAttribute<br />
List getElems() ;<br />
}<br />
@ManagedObject<br />
public interface Baz {<br />
@ManagedAttribute<br />
Foo getFoo()<br />
}<br />
Foo is annotated as @ManagedData<br />
Needs to be OpenData<br />
But we can’t tell what type T is in Foo<br />
Baz has an instance of Foo with T<br />
instantiated to Bar<br />
Note that Foo also has an instance of the<br />
standard List, with is declared with its own<br />
type variable T (see java.util.List)<br />
Typelib replaces all type variables with the<br />
values to which they are bound<br />
It is a bit tricky due to the need to handle<br />
complex recursive references to types<br />
Friday, December 11, 2009<br />
20
org.glassfish.gmbal.impl<br />
<strong>The</strong> main implementation package<br />
Classes:<br />
ManagedObjectManagerInternal (interface for MOM used in impl<br />
package)<br />
ManagedObjectManagerImpl<br />
MBeanSkeleton (contains most of the implementation for a specific<br />
MBean)<br />
MBeanImpl (actually class used to represent MBean)<br />
MBeanTree (containment hierarchy of MBeans)<br />
JMXRegistrationManager (manages MBean registrations)<br />
TypeConverter(Impl) (handle java type open type conversions)<br />
AttributeDescriptor (main implementation of attributes)<br />
AMXImpl (implements AMX attributes)<br />
Friday, December 11, 2009<br />
21
Tools and test support<br />
org.glassfish.gmbal.tools.argparser<br />
Attribute driven command line parser<br />
org.glassfish.gmbal.tools.file<br />
General purpose file and directory processing tools from CORBA<br />
Used here to generate resource bundle for logex exception<br />
wrappers<br />
org.glassfish.gmbal.main<br />
Provides ProfileMain, which is used for simple performance testing<br />
None of this code is delivered in the OSGi bundles for <strong>Gmbal</strong><br />
Friday, December 11, 2009<br />
22
Construction and Registration 1<br />
ManagedObjectManagerImpl data:<br />
MBeanTree (maintains registration of all MBeans for this MOM)<br />
skeletonMap (maps class to skeleton)<br />
typeConverterMap (maps class to type converter)<br />
Registration starts at ManagedObjectManagerImpl.register( Object<br />
parent, Object obj, String name )<br />
get the MBeanImpl corresponding to the parent<br />
construct the MBean for obj<br />
register the MBean in the tree<br />
Friday, December 11, 2009<br />
23
Construction and Registration 2<br />
ConstructMBean<br />
Use typelib to get an EvaluatedType for the class of obj<br />
get a skeleton for the evaluated type<br />
Analyzes the annotations for attributes and operations<br />
gets the TypeConverters for all attribute and operation types<br />
Constructs the JMX metadata for all types, attributes, and<br />
operations<br />
construct AMX Metadata<br />
construct MBeanImpl<br />
Friday, December 11, 2009<br />
24
Attributes and Operations<br />
MBeanImpl implements the dynamic MBean interface by delegating to<br />
the MBeanSkeleton<br />
MBeanImpl implements the FacetAccessor interface<br />
MBeanSkeleton uses the appropriate AttributeDescriptor for<br />
attribute get/set<br />
<strong>The</strong> AttributeDescriptor uses the FacetAccessor interface to get/set<br />
the actual attribute value (either from a method or a field)<br />
<strong>The</strong> AttributeDescriptor also uses the TypeConverter to convert to/<br />
from the OpenType as needed<br />
Friday, December 11, 2009<br />
25
Debugging: MethodMonitor<br />
Most of the code in typelib and impl uses the MethodMonitor<br />
Allows internal tracing of method entry, exit, and other interesting<br />
points in the method<br />
Currently used for two purposes:<br />
To record interesting context in the OperationTracer<br />
To hook in DprintUtil for support of debug flags, which are<br />
controlled by the debug methods<br />
Friday, December 11, 2009<br />
26
Example of OperationTracer<br />
INFO: GMBAL406: registering MBean extern:pp=/gmbal-root/AMXClientTest$MyManagedClass[Root]/AMXClientTest<br />
$MyManagedClass[Child],type=AMXClientTest$MyManagedClass,name=GrandChild-2<br />
CONTEXT:<br />
( 0): register(org.glassfish.gmbal.impl.AMXClientTest$MyManagedClass@1d2b9b7,org.glassfish.gmbal.impl.AMXClientTest<br />
$MyManagedClass@19c0bd6,)<br />
( 1): register(MBeanImpl[type=AMXClientTest$MyManagedClass,name=Child,oname=extern:pp=/gmbal-root/AMXClientTest<br />
$MyManagedClass[Root],type=AMXClientTest$MyManagedClass,name=Child],org.glassfish.gmbal.impl.AMXClientTest<br />
$MyManagedClass@19c0bd6,MBeanImpl[type=AMXClientTest$MyManagedClass,name=GrandChild-2,oname=extern:pp=/gmbal-root/<br />
AMXClientTest$MyManagedClass[Root]/AMXClientTest$MyManagedClass[Child],type=AMXClientTest<br />
$MyManagedClass,name=GrandChild-2])<br />
java.lang.RuntimeException: StackTrace<br />
at org.glassfish.gmbal.logex.WrapperGenerator.makeException(WrapperGenerator.java:220)<br />
at org.glassfish.gmbal.logex.WrapperGenerator.handleFullLogging(WrapperGenerator.java:361)<br />
at org.glassfish.gmbal.logex.WrapperGenerator.access$300(WrapperGenerator.java:93)<br />
at org.glassfish.gmbal.logex.WrapperGenerator$1.invoke(WrapperGenerator.java:434)<br />
at $Proxy16.registeringMBean(Unknown Source)<br />
at org.glassfish.gmbal.impl.MBeanImpl.register(MBeanImpl.java:303)<br />
at org.glassfish.gmbal.impl.JMXRegistrationManager.register(JMXRegistrationManager.java:193)<br />
at org.glassfish.gmbal.impl.MBeanTree.register(MBeanTree.java:376)<br />
at org.glassfish.gmbal.impl.ManagedObjectManagerImpl.register(ManagedObjectManagerImpl.java:713)<br />
at org.glassfish.gmbal.impl.ManagedObjectManagerImpl.register(ManagedObjectManagerImpl.java:724)<br />
at org.glassfish.gmbal.impl.AMXClientTest.initializeMom(AMXClientTest.java:195)<br />
at org.glassfish.gmbal.impl.AMXClientTest.setUp(AMXClientTest.java:176)<br />
•This is taken from a test case which is registering an MBean<br />
•<strong>The</strong> context indicates the data being registered<br />
•( 0): This is the main register method discussed previously<br />
•( 1): This is the MBeanTree register call<br />
•Here we see a fully constructed MBean being registered under<br />
the parent<br />
•This gives information not available in the stack trace<br />
•<strong>The</strong> OperationTracer is avilable for all <strong>Gmbal</strong> exceptions<br />
Friday, December 11, 2009<br />
27
<strong>The</strong> debug methods<br />
<strong>Gmbal</strong> has a number of methods that can be set to display more<br />
information<br />
<strong>The</strong>re is no general user-exposed API for this<br />
But note that some of the <strong>Gmbal</strong> debug can be enabled using the<br />
ORB debug flags within the ORB<br />
All of the debug flags enabled various MethodMonitor calls which<br />
print out information in a method:<br />
On entry: ($thread): (GMBAL).impl..-><br />
Info: ($thread): (GMBAL).impl..::<br />
On exit: ($thread): (GMBAL).impl..
<strong>Gmbal</strong> tests<br />
<strong>Gmbal</strong> has an extensive test suite in the <strong>project</strong><br />
tests use the same package names as source, but are in a different<br />
directory (standard NB <strong>project</strong> layout)<br />
Main test is in org.glassfish.gmbal.JmxaTest (old name)<br />
Emma reports pretty good code coverage<br />
block 69%<br />
class 78%<br />
line 69%<br />
method 69%<br />
Hudson job is at http://hudson.sfbay/view/corba/gmbal<br />
Unfortunately the job is currently broken<br />
Friday, December 11, 2009<br />
29
Common Errors in Using <strong>Gmbal</strong><br />
Just a few examples<br />
I don’t have time to do complete documentation on these<br />
Examples:<br />
Registering the same object twice<br />
Unregistering an object that was previously unregistered<br />
Passing something to a register method that cannot represent an<br />
MBean (e.g. no @ManagedObject annotation)<br />
Putting @ManagedAttribute on a method that is not a valid<br />
attribute (e.g. return non-void and takes an argument)<br />
Annotating object with @AMXMetadata( isSingleton = true ) and<br />
then creating more than one instance<br />
Forgetting @NameValue on an object registered without a name<br />
Friday, December 11, 2009<br />
30