Interface Invoker<T,R>

Type Parameters:
T - type of the target instance
R - return type of the method

public interface Invoker<T,R>
Allows indirectly invoking a method that belongs to a managed bean (the target method). To invoke the method, the caller must provide all the arguments that the target method accepts, as well as the instance on which the target method is to be invoked, if it is not static.

Whenever a direct invocation of a method is a business method invocation, an indirect invocation of that method through an invoker is also a business method invocation.

Invoker implementations must be thread-safe. It is possible to use a single invoker instance to perform multiple independent invocations of the target method, possibly on different instances and with different arguments.

Obtaining an invoker

The CDI container allows building an invoker for non-private methods declared on a managed bean class or inherited from a supertype. Attempting to build an invoker for a private method or a constructor of a managed bean class leads to a deployment problem. Attempting to build an invoker for a method of a class that is not a managed bean class or that is an interceptor or decorator class leads to a deployment problem.

Multiple managed beans may inherit a method from a common supertype. In that case, each bean conceptually has its own method and an invoker obtained for one bean may not be used to invoke the method on the other bean.

Using the InvokerBuilder is the only way to obtain an invoker. An InvokerBuilder can only be obtained in CDI portable extensions and build compatible extensions.

Example

To illustrate how invokers work, let's take a look at an example. Say that the following bean exists and has a method that you want to invoke indirectly:
 @Dependent
 class MyService {
     String hello(String name) {
         return "Hello " + name + "!";
     }
 }
 
When you obtain an InvokerBuilder for the hello() method, you can immediately build a direct invoker. In a portable extension, this results in an invoker:
 InvokerBuilder<Invoker<MyService, String>> builder = ...;
 Invoker<MyService, String> invoker = builder.build();
 
In a build compatible extension, this results in an opaque token that later materializes as an invoker:
 InvokerBuilder<InvokerInfo> builder = ...;
 InvokerInfo invoker = builder.build();
 
To call the hello() method through this invoker, call invoker.invoke(myService, new Object[] {"world"}). The return value is "Hello world!".

An implementation of the direct invoker above is equivalent to the following class:

 class TheInvoker implements Invoker<MyService, String> {
     String invoke(MyService instance, Object[] arguments) {
         return instance.hello((String) arguments[0]);
     }
 }
 
Since:
4.1
See Also:
  • Method Summary

    Modifier and Type
    Method
    Description
    invoke(T instance, Object[] arguments)
    Invokes the target method of this invoker on given instance, passing given arguments.
  • Method Details

    • invoke

      R invoke(T instance, Object[] arguments)
      Invokes the target method of this invoker on given instance, passing given arguments. If the target method is static, the instance is ignored; by convention, it should be null. If the target method returns normally, this method returns its return value, unless the target method is declared void, in which case this method returns null. If the target method throws an exception, this method rethrows it directly.

      If some parameter of the target method declares a primitive type, the corresponding element of the arguments array must be of the corresponding wrapper type. No type conversions are performed, so if the parameter is declared int, the argument must be an Integer and may not be Short or Long. If the argument is null, the default value of the primitive type is used. Note that this does not apply to arrays of primitive types; if a parameter is declared int[], the argument must be int[] and may not be Integer[].

      If the target method is not static and instance is null, a NullPointerException is thrown. If the target method is not static and the instance is not assignable to the class of the bean to which the method belongs, a ClassCastException is thrown.

      If the target method declares no parameter, arguments are ignored. If the target method declares any parameter and arguments is null, NullPointerException is thrown. If the arguments array has fewer elements than the number of parameters of the target method, ArrayIndexOutOfBoundsException is thrown. If the arguments array has more elements than the number of parameters of the target method, the excess elements are ignored. If some of the arguments is not assignable to the declared type of the corresponding parameter of the target method, ClassCastException is thrown. TODO the previous 2 paragraphs refer to "assignability", which needs to be defined somewhere! TODO when the `InvokerBuilder` applies transformations, some of the requirements above are no longer strictly necessary, should reflect that in this text somehow (it is already mentioned in `InvokerBuilder`, but that likely isn't enough)

      Parameters:
      instance - the instance on which the target method is to be invoked, may only be null if the method is static
      arguments - arguments to be supplied to the target method, may only be null if the method declares no parameter
      Returns:
      return value of the target method, or null if the method is declared void