2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.sal.binding.api;
10 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
11 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
12 import org.opendaylight.yangtools.yang.binding.RpcService;
15 * Provides a registry for Remote Procedure Call (RPC) service implementations. The RPCs are defined
18 * There are 2 types of RPCs:
26 * An RPC is global if there is intended to be only 1 registered implementation. A global RPC is not
27 * explicitly declared as such, essentially any RPC that is not defined to be routed is considered
30 * Global RPCs are registered using the {@link #addRpcImplementation(Class, RpcService)} method.
34 * MD-SAL supports routing of RPC between multiple implementations where the appropriate
35 * implementation is selected at run time based on the content of the RPC message as described in
38 * RPC routing is based on:
40 * <li><b>Route identifier</b> - An
41 * {@link org.opendaylight.yangtools.yang.binding.InstanceIdentifier InstanceIdentifier} value which
42 * is part of the RPC input. This value is used to select the correct implementation at run time.</li>
43 * <li><b>Context Type</b> - A YANG-defined construct which constrains the subset of valid route
44 * identifiers for a particular RPC.</li>
47 * <h3>Context type</h3>
49 * A context type is modeled in YANG using a combination of a YANG <code>identity</code> and
50 * Opendaylight specific extensions from <code>yang-ext</code> module. These extensions are:
52 * <li><b>context-instance</b> - This is used in the data tree part of a YANG model to define a
53 * context type that associates nodes with a specified context <code>identity</code>. Instance
54 * identifiers that reference these nodes are valid route identifiers for RPCs that reference this
56 * <li><b>context-reference</b> - This is used in RPC input to mark a leaf of type
57 * <code>instance-identifier</code> as a reference to the particular context type defined by the
58 * specified context <code>identity</code>. The value of this leaf is used by the RPC broker at run
59 * time to route the RPC request to the correct implementation. Note that
60 * <code>context-reference</code> may only be used on leaf elements of type
61 * <code>instance-identifier</code> or a type derived from <code>instance-identifier</code>.</li>
65 * <h3>Routed RPC example</h3>
67 * <h4>1. Defining a Context Type</h4>
69 * The following snippet declares a simple YANG <code>identity</code> named
70 * <code>example-context</code>:
75 * identity example-context {
76 * description "Identity used to define an example-context type";
82 * We then use the declared identity to define a context type by using it in combination with the
83 * <code>context-instance</code> YANG extension. We'll associate the context type with a list
84 * element in the data tree. This defines the set of nodes whose instance identifiers are valid for
85 * the <code>example-context</code> context type.
87 * The following YANG snippet imports the <code>yang-ext</code> module and defines the list element
88 * named <code>item</code> inside a container named <code>foo</code>:
93 * import yang-ext {prefix ext;}
98 * leaf id {type string;}
99 * ext:context-instance "example-context";
106 * The statement <code>ext:context-instance "example-context";</code> inside the list element
107 * declares that any instance identifier referencing <code>item</code> in the data tree is valid for
108 * <code>example-context</code>. For example, the following instance identifier:
111 * InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey("Foo"))
114 * is valid for <code>example-context</code>. However the following:
117 * InstanceIdentifier.create(Example.class)
122 * So using an <code>identity</code> in combination with <code>context-instance</code> we have
123 * effectively defined a context type that can be referenced in a YANG RPC input.
125 * <h5>2. Defining an RPC to use the Context Type</h5>
127 * To define an RPC to be routed based on the context type we need to add an input leaf element that
128 * references the context type which will hold an instance identifier value to be used to route the
131 * The following snippet defines an RPC named <code>show-item</code> with 2 leaf elements as input:
132 * <code>item</code> of type <code>instance-identifier</code> and <code>description</code>:
137 * import yang-ext {prefix ext;}
142 * type instance-identifier;
143 * ext:context-reference example-context;
153 * We mark the <code>item</code> leaf with a <code>context-reference</code> statement that
154 * references the <code>example-context</code> context type. RPC calls will then be routed based on
155 * the instance identifier value contained in <code>item</code>. Only instance identifiers that
156 * point to a <code>foo/item</code> node are valid as input.
158 * The generated RPC Service interface for the module is:
161 * interface FooService implements RpcService {
162 * Future<RpcResult<Void>> showItem(ShowItemInput input);
166 * For constructing the RPC input, there are generated classes ShowItemInput and
167 * ShowItemInputBuilder.
169 * <h5>3. Registering a routed RPC implementation</h5>
171 * To register a routed implementation for the <code>show-item</code> RPC, we must use the
172 * {@link #addRoutedRpcImplementation(Class, RpcService)} method. This will return a
173 * {@link RoutedRpcRegistration} instance which can then be used to register / unregister routed
174 * paths associated with the registered implementation.
176 * The following snippet registers <code>myImpl</code> as the RPC implementation for an
177 * <code>item</code> with key <code>"foo"</code>:
180 * // Create the instance identifier path for item "foo"
181 * InstanceIdentifier path = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey("foo"));
183 * // Register myImpl as the implementation for the FooService RPC interface
184 * RoutedRpcRegistration reg = rpcRegistry.addRoutedRpcImplementation(FooService.class, myImpl);
186 * // Now register for the context type and specific path ID. The context type is specified by the
187 * // YANG-generated class for the example-context identity.
188 * reg.registerPath(ExampleContext.class, path);
191 * It is also possible to register the same implementation for multiple paths:
194 * InstanceIdentifier one = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey("One"));
195 * InstanceIdentifier two = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey("Two"));
197 * RoutedRpcRegistration reg = rpcRegistry.addRoutedRpcImplementation(FooService.class, myImpl);
198 * reg.registerPath(ExampleContext.class, one);
199 * reg.registerPath(ExampleContext.class, two);
203 * When another client invokes the <code>showItem(ShowItemInput)</code> method on the proxy instance
204 * retrieved via {@link RpcConsumerRegistry#getRpcService(Class)}, the proxy will inspect the
205 * arguments in ShowItemInput, extract the InstanceIdentifier value of the <code>item</code> leaf
206 * and select the implementation whose registered path matches the InstanceIdentifier value of the
207 * <code>item</code> leaf.
209 * <h2>Notes for RPC Implementations</h2>
213 * The generated interfaces require implementors to return {@link java.util.concurrent.Future
214 * Future}<{@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult}
215 * <{RpcName}Output>> instances.
217 * Implementations should do processing of RPC calls asynchronously and update the returned
218 * {@link java.util.concurrent.Future Future} instance when processing is complete. However using
219 * {@link com.google.common.util.concurrent.Futures#immediateFuture(Object) Futures.immediateFuture}
220 * is valid only if the result is immediately available and asynchronous processing is unnecessary
221 * and would only introduce additional complexity.
224 * The {@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult} is a generic wrapper for
225 * the RPC output payload, if any, and also allows for attaching error or warning information
226 * (possibly along with the payload) should the RPC processing partially or completely fail. This is
227 * intended to provide additional human readable information for users of the API and to transfer
228 * warning / error information across the system so it may be visible via other external APIs such
231 * It is recommended to use the {@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult}
232 * for conveying appropriate error information on failure rather than purposely throwing unchecked
233 * exceptions if at all possible. While unchecked exceptions will fail the returned
234 * {@link java.util.concurrent.Future Future}, using the intended RpcResult to convey the error
235 * information is more user-friendly.
237 public interface RpcProviderRegistry extends RpcConsumerRegistry {
239 * Registers a global implementation of the provided RPC service interface.
240 * All methods of the interface are required to be implemented.
242 * @param serviceInterface the YANG-generated interface of the RPC Service for which to register.
243 * @param implementation "the implementation of the RPC service interface.
244 * @return an RpcRegistration instance that should be used to unregister the RPC implementation
245 * when no longer needed by calling {@link RpcRegistration#close()}.
247 * @throws IllegalStateException
248 * if the supplied RPC interface is a routed RPC type.
250 <T extends RpcService> RpcRegistration<T> addRpcImplementation(Class<T> serviceInterface, T implementation)
251 throws IllegalStateException;
254 * Registers an implementation of the given routed RPC service interface.
256 * See the {@link RpcProviderRegistry class} documentation for information and example on how to
259 * @param serviceInterface the YANG-generated interface of the RPC Service for which to
261 * @param implementation the implementation instance to register.
262 * @return a RoutedRpcRegistration instance which can be used to register paths for the RPC
263 * implementation via invoking
264 * {@link RoutedRpcRegistration#registerPath(Class, org.opendaylight.yangtools.yang.binding.InstanceIdentifier)}
265 * . {@link RoutedRpcRegistration#close()} should be called to unregister the
266 * implementation and all previously registered paths when no longer needed.
268 * @throws IllegalStateException if the supplied RPC interface is not a routed RPC type.
270 <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> serviceInterface,
272 throws IllegalStateException;