Annotation Interface Inheritance
MethodTransaction
and
ClassTransaction
.
When a method is instrumented so that each invocation creates a transaction, there remains a choice with respect
to the handling of overridden methods in derived classes.
By default, overridden methods are ignored, so an overridden method that does not call super()
, will not
create a transaction. This also applies to implementations of abstract methods, so if you annotate an interface
with @ClassTransaction
, no transactions will be created by default.
By setting the MethodTransaction.inheritance()
or ClassTransaction.inheritance()
parameters to
something other than Inheritance.Mode.NONE
, overridden and implemented methods will be considered as well.
If an overridden method calls super()
in that case, you can prevent additional transactions by choosing
a naming scheme that does not differ for subclasses or by setting an appropriate ReentryInhibition
value
for the transaction.
Interfaces vs. proxies
When inheritance is used and perfino processes an overridden or implementing method that is annotated as a transaction in a super class or interface, there are two choices when adding class names to the transaction name:
-
When you provide your own implementations of an interface, the implementations often have different tasks
that should be monitored separately. In that case, you want to see the derived class names in transaction names.
This is achieved by using
Inheritance.Mode.WITH_SUBCLASS_NAMES
.For example:
@MethodTransaction(inheritance = @Inheritance(Mode.WITH_SUBCLASS_NAMES))
Since
Mode.WITH_SUBCLASS_NAMES
is the default value ofvalue()
, you can leave it out and the previous example is equivalent to@MethodTransaction(inheritance = @Inheritance)
-
In a situation where a framework is creating proxies from an annotated class or interface, such as for an EJB, the
class name of the proxy class is not useful for monitoring. It often has an uninterpretable class name and changes
each time the VM is restarted or even more often. Similarly, you may be implementing your own interface, but the
implementations are all different implementations of the same task and should not be shown as separate transactions.
For these situations, you should use
Inheritance.Mode.WITH_SUPERCLASS_NAME
. In that mode, the name of the annotated class will be used for transaction names. For example:@MethodTransaction(inheritance = @Inheritance(Mode.WITH_SUPERCLASS_NAME))
Since no explicit
naming
has been specified, the default naming of@Part(Type.CLASS)
will be used, so there will only be a single transaction with the simple name of the annotated class followed by the name of the annotated method.
Marker interfaces vs. regular interfaces
For a ClassTransaction
, all public methods are annotated. If
Inheritance.Mode.WITH_SUBCLASS_NAMES
or
Inheritance.Mode.WITH_SUPERCLASS_NAME
are used as the inheritance mode,
all public methods in derived classes are annotated as well, regardless of whether they override
or implement methods in the annotated class. This is desirable if the methods of interest
are not present in the super-class or interface. In the most extreme case, a marker interface has no methods at all,
and all methods are in derived classes.
If some public methods in derived classes should not be instrumented, you can use
NoTransaction
to exclude entire classes or selected methods from
transaction processing.
However, in cases where the annotated class or interface already defines all methods of interest, you can
choose to ignore other public methods in derived classes by setting the implementingOnly()
parameter
to true
. Only overriding or implementing methods in derived classes will then create transactions.
Filters
In the inheritance hierarchy, you may want to exclude certain classes. This is done with the filter()
parameter. The filter is evaluated against the class name as determined by the value()
parameter
and can be a wildcard filter or a regular expression filter, depending of the value of the
filterType()
parameter.
For example, the
@MethodTransaction(inheritance = @Inheritance(filter = "*Executor*"))
only instruments methods in classes that match the specified wildcard filter.
-
Nested Class Summary
Nested Classes -
Optional Element Summary
Optional ElementsModifier and TypeOptional ElementDescriptionThe filter for selecting derived classes.The type of the filter expression.boolean
Determines handling of methods in derived classes that are not present in the superclass.The inheritance mode.
-
Element Details
-
value
Inheritance.Mode valueThe inheritance mode. While the default value isInheritance.Mode.WITH_SUBCLASS_NAMES
, the default inheritance mode ofMethodTransaction
andClassTransaction
isInheritance.Mode.NONE
.See
Inheritance
for a description of the different modes.- Default:
WITH_SUBCLASS_NAMES
-
filter
String filterThe filter for selecting derived classes. By default, the filter is a wildcard filter with filter expression "*", so all derived classes are matched ifvalue()
is set to something other thanInheritance.Mode.NONE
. SeeFilterType
for the syntax of filter expressions andInheritance
for a description of filters.- Default:
"*"
-
filterType
FilterType filterTypeThe type of the filter expression. By default,wildcard filters
are used, butregular expression filters
are also available for more complex expressions.- Default:
WILDCARD
-
implementingOnly
boolean implementingOnlyDetermines handling of methods in derived classes that are not present in the superclass. This parameter only has an effect if used in the context of aClassTransaction
and ifvalue()
is set toInheritance.Mode.WITH_SUBCLASS_NAMES
orInheritance.Mode.WITH_SUPERCLASS_NAME
.If set to
true
, only overriding or implementing public methods in derived classes are instrumented. If set tofalse
, all public methods in derived classes are instrumented. In that case, you can still useNoTransaction
to exclude selected derived classes or selected public methods in them.- Default:
false
-