Interface RpcProviderRegistry

  • All Superinterfaces:
    BindingAwareService, BindingService, RouteChangePublisher<RpcContextIdentifier,​InstanceIdentifier<?>>, RpcConsumerRegistry
    All Known Subinterfaces:
    BindingAwareBroker.ProviderContext
    All Known Implementing Classes:
    AbstractBindingSalProviderInstance, HeliumRpcProviderRegistry, RootBindingAwareBroker, RootBindingAwareBroker.RootSalInstance

    @Deprecated(forRemoval=true)
    public interface RpcProviderRegistry
    extends RpcConsumerRegistry, RouteChangePublisher<RpcContextIdentifier,​InstanceIdentifier<?>>
    Deprecated, for removal: This API element is subject to removal in a future version.
    Use RpcProviderService instead
    Provides a registry for Remote Procedure Call (RPC) service implementations. The RPCs are defined in YANG models.

    There are 2 types of RPCs:

    • Global
    • Routed

    Global RPC

    An RPC is global if there is intended to be only 1 registered implementation. A global RPC is not explicitly declared as such, essentially any RPC that is not defined to be routed is considered global.

    Global RPCs are registered using the addRpcImplementation(Class, RpcService) method.

    Routed RPC

    MD-SAL supports routing of RPC between multiple implementations where the appropriate implementation is selected at run time based on the content of the RPC message as described in YANG model.

    RPC routing is based on:

    • Route identifier - An InstanceIdentifier value which is part of the RPC input. This value is used to select the correct implementation at run time.
    • Context Type - A YANG-defined construct which constrains the subset of valid route identifiers for a particular RPC.

    Context type

    A context type is modeled in YANG using a combination of a YANG identity and Opendaylight specific extensions from yang-ext module. These extensions are:

    • context-instance - This is used in the data tree part of a YANG model to define a context type that associates nodes with a specified context identity. Instance identifiers that reference these nodes are valid route identifiers for RPCs that reference this context type.
    • context-reference - This is used in RPC input to mark a leaf of type instance-identifier as a reference to the particular context type defined by the specified context identity. The value of this leaf is used by the RPC broker at run time to route the RPC request to the correct implementation. Note that context-reference may only be used on leaf elements of type instance-identifier or a type derived from instance-identifier.


    1. Defining a Context Type

    The following snippet declares a simple YANG identity named example-context: module example { ... identity example-context { description "Identity used to define an example-context type"; } ... }

    We then use the declared identity to define a context type by using it in combination with the context-instance YANG extension. We'll associate the context type with a list element in the data tree. This defines the set of nodes whose instance identifiers are valid for the example-context context type.

    The following YANG snippet imports the yang-ext module and defines the list element named item inside a container named foo: module foo { ... import yang-ext {prefix ext;} ... container foo { list item { key "id"; leaf id {type string;} ext:context-instance "example-context"; } } ... }

    The statement ext:context-instance "example-context"; inside the list element declares that any instance identifier referencing item in the data tree is valid for example-context. For example, the following instance identifier:

         InstanceIdentifier.create(Foo.class).child(Item.class,new ItemKey("Foo"))
     
    is valid for example-context. However the following:
         InstanceIdentifier.create(Example.class)
     
    is not valid.

    So using an identity in combination with context-instance we have effectively defined a context type that can be referenced in a YANG RPC input.

    2. Defining an RPC to use the Context Type

    To define an RPC to be routed based on the context type we need to add an input leaf element that references the context type which will hold an instance identifier value to be used to route the RPC.

    The following snippet defines an RPC named show-item with 2 leaf elements as input: item of type instance-identifier and description:

     module foo {
          ...
          import yang-ext {prefix ext;}
          ...
          rpc show-item {
              input {
                  leaf item {
                      type instance-identifier;
                      ext:context-reference example-context;
                  }
                  leaf description {
                      type "string";
                  }
              }
          }
     }
     

    We mark the item leaf with a context-reference statement that references the example-context context type. RPC calls will then be routed based on the instance identifier value contained in item. Only instance identifiers that point to a foo/item node are valid as input.

    The generated RPC Service interface for the module is:

     interface FooService implements RpcService {
          Future<RpcResult<Void>> showItem(ShowItemInput input);
     }
     

    For constructing the RPC input, there are generated classes ShowItemInput and ShowItemInputBuilder.

    3. Registering a routed RPC implementation

    To register a routed implementation for the show-item RPC, we must use the addRoutedRpcImplementation(Class, RpcService) method. This will return a BindingAwareBroker.RoutedRpcRegistration instance which can then be used to register / unregister routed paths associated with the registered implementation.

    The following snippet registers myImpl as the RPC implementation for an item with key "foo":

     // Create the instance identifier path for item "foo"
     InstanceIdentifier path = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey("foo"));
    
     // Register myImpl as the implementation for the FooService RPC interface
     RoutedRpcRegistration reg = rpcRegistry.addRoutedRpcImplementation(FooService.class, myImpl);
    
     // Now register for the context type and specific path ID. The context type is specified by the
     // YANG-generated class for the example-context identity.
     reg.registerPath(ExampleContext.class, path);
     

    It is also possible to register the same implementation for multiple paths:

     InstanceIdentifier one = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey("One"));
     InstanceIdentifier two = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey("Two"));
    
     RoutedRpcRegistration reg = rpcRegistry.addRoutedRpcImplementation(FooService.class, myImpl);
     reg.registerPath(ExampleContext.class, one);
     reg.registerPath(ExampleContext.class, two);
     

    When another client invokes the showItem(ShowItemInput) method on the proxy instance retrieved via RpcConsumerRegistry.getRpcService(Class), the proxy will inspect the arguments in ShowItemInput, extract the InstanceIdentifier value of the item leaf and select the implementation whose registered path matches the InstanceIdentifier value of the item leaf.


    Notes for RPC Implementations

    RpcResult

    The generated interfaces require implementors to return Future<RpcResult <{RpcName}Output>> instances.

    Implementations should do processing of RPC calls asynchronously and update the returned Future instance when processing is complete. However using Futures.immediateFuture is valid only if the result is immediately available and asynchronous processing is unnecessary and would only introduce additional complexity.

    The RpcResult is a generic wrapper for the RPC output payload, if any, and also allows for attaching error or warning information (possibly along with the payload) should the RPC processing partially or completely fail. This is intended to provide additional human readable information for users of the API and to transfer warning / error information across the system so it may be visible via other external APIs such as Restconf.

    It is recommended to use the RpcResult for conveying appropriate error information on failure rather than purposely throwing unchecked exceptions if at all possible. While unchecked exceptions will fail the returned Future, using the intended RpcResult to convey the error information is more user-friendly.

    • Method Detail

      • addRpcImplementation

        <T extends RpcServiceBindingAwareBroker.RpcRegistration<T> addRpcImplementation​(Class<T> serviceInterface,
                                                                                          T implementation)
                                                                                   throws IllegalStateException
        Deprecated, for removal: This API element is subject to removal in a future version.
        Registers a global implementation of the provided RPC service interface. All methods of the interface are required to be implemented.
        Parameters:
        serviceInterface - the YANG-generated interface of the RPC Service for which to register.
        implementation - "the implementation of the RPC service interface.
        Returns:
        an RpcRegistration instance that should be used to unregister the RPC implementation when no longer needed by calling BindingAwareBroker.RpcRegistration.close().
        Throws:
        IllegalStateException - if the supplied RPC interface is a routed RPC type.
      • addRoutedRpcImplementation

        <T extends RpcServiceBindingAwareBroker.RoutedRpcRegistration<T> addRoutedRpcImplementation​(Class<T> serviceInterface,
                                                                                                      T implementation)
                                                                                               throws IllegalStateException
        Deprecated, for removal: This API element is subject to removal in a future version.
        Registers an implementation of the given routed RPC service interface.

        See the class documentation for information and example on how to use routed RPCs.

        Parameters:
        serviceInterface - the YANG-generated interface of the RPC Service for which to register.
        implementation - the implementation instance to register.
        Returns:
        a RoutedRpcRegistration instance which can be used to register paths for the RPC implementation via invoking RoutedRpcRegistration#registerPath(Class, InstanceIdentifer). BindingAwareBroker.RpcRegistration.close() should be called to unregister the implementation and all previously registered paths when no longer needed.
        Throws:
        IllegalStateException - if the supplied RPC interface is not a routed RPC type.