Annotation Interface Inheritance


@Target({}) public @interface Inheritance
Controls the way overridden methods will be handled by 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 of value(), 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
    Modifier and Type
    Class
    Description
    static enum 
    Mode for handling derived classes.
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    The 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.