Hello World - RPC





1.Build the project

Eclipse menu File > New > Project > Maven > Maven Project, Next; Advanced: Name template: [groupId].[artifactId], and then check [X] Include snapshot archetypes, and choose Artifact Id opendaylight-startup-archetype. 


2. Build and Run the maven project

gin1994@ubuntu:~/workspace/helloproject-aggregator$ mvn clean install
gin1994@ubuntu:~/workspace/helloproject-aggregator$ cd karaf/target/assembly/bin
gin1994@ubuntu:~/workspace/helloproject-aggregator/karaf/target/assembly/bin$ ./karaf

opendaylight-user@root>log:display | grep Hello
2017-02-19 11:35:05,301 | INFO  | rint Extender: 3 | HelloprojectProvider    
 | 216 - org.gin.hello.project-impl - 0.1.0.SNAPSHOT | HelloprojectProvider Session Initiated


opendaylight-user@root>shutdown -f



Return to the top of the directory structure:
gin1994@ubuntu:~/workspace/helloproject-aggregator/karaf/target/assembly/bin$ cd ../../../../

3.Diving the project

3.1 Understanding where the log line came from (the entry point)


The entry point is in the impl project:

impl/src/main/java/org/opendaylight/hello/impl/HelloProvider.java
In the HelloProvider.init method:

    public void init() {
        LOG.info("HelloProvider Session Initiated");
    }


3.2.Adding a very simple HelloWorld RPC api


api/src/main/yang/hello.yang

module hello {
    yang-version 1;
    namespace "urn:opendaylight:params:xml:ns:yang:hello";
    prefix "hello";

    revision "2015-01-05" {
        description "Initial revision of hello model";
    }
    rpc hello-world {
        input {
            leaf name {
                type string;
            }
        }
        output {
            leaf greeting {
                type string;
            }
        }
    }
}

In eclipse, go to hello-api POM.xml, Run As > Maven generate-sources.如果不行 试试 Maven install

Or,in CLI, 
cd ../../../
mvn clean install




3.3.Implementing the HelloWorld RPC API



cd ../impl/src/main/java/org/opendaylight/hello/impl/





Create a new file called HelloWorldImpl.java and add in the code below.




package org.opendaylight.hello.impl;

import java.util.concurrent.Future;

import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldOutputBuilder;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;

public class HelloWorldImpl implements HelloService {

    @Override
    public Future<RpcResult<HelloWorldOutput>> helloWorld(HelloWorldInput input) {
        HelloWorldOutputBuilder helloBuilder = new HelloWorldOutputBuilder();
        helloBuilder.setGreeting("Hello " + input.getName());
        return RpcResultBuilder.success(helloBuilder.build()).buildFuture();
    }

}

helloWorld Method:

1.java.util.concurrent.Future<RpcResult<HelloWorldOutput>>


A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready. Cancellation is performed by the cancel method. Additional methods are provided to determine if the task completed normally or was cancelled. Once a computation has completed, the computation cannot be cancelled. If you would like to use a Future for the sake of cancellability but not provide a usable result, you can declare types of the form Future<?> and return null as a result of the underlying task.

2.org.opendaylight.yangtools.yang.common.RpcResult<HelloWorldOutput>:
Represents a general result of a call, request, or operation.
Type Parameters:
<T> the result value type

3.org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldOutputBuilder

Class that builds org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldOutput instances.

4.org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldOutput

This class represents the following YANG schema fragment defined in module hello

 container output {
     leaf greeting {
         type string;
     }
 }

The schema path to identify an instance is hello/hello-world/output
To create instances of this class use org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldOutputBuilder.

5.HelloWorldOutputBuilder org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldOutputBuilder.setGreeting(String value)

6.String org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldInput.getName()

7.<HelloWorldOutput> RpcResultBuilder<HelloWorldOutput> org.opendaylight.yangtools.yang.common.RpcResultBuilder.success(HelloWorldOutput result)

Returns a builder for a successful result.

Type Parameters:
<T>
Parameters:
result the result value


8.ListenableFuture<RpcResult<HelloWorldOutput>> org.opendaylight.yangtools.yang.common.RpcResultBuilder.buildFuture()

Builds RpcResult and wraps it in a Future This is a convenience method to assist those writing rpcs that produce immediate results. It allows you to replace Futures.immediateFuture(rpcResult.build()) with rpcResult.buildFuture();





3.4 In order to register our RPC with MD-SAL,
we first need to create the reference to the RPC Registry. This is done in a couple of steps. First, we need to add the RPC Registry reference to the impl-blueprint.xml file in src/main/resources/org/opendaylight/blueprint as follows:
  • We add a line that defines the reference to the implementation of the RPC Registry interface (org.opendaylight.controller.sal.binding.api.RpcProviderRegistry). We call the reference rpcRegistry.
  • We add the reference to the implementation of the RPC Registry interface to the parameters of the "HelloProvider" constructor.


 <?xml version="1.0" encoding="UTF-8"?>
 <!-- vi: set et smarttab sw=4 tabstop=4: -->
 <!--
 Copyright © 2016 Cisco Systems and others. All rights reserved.
 
 This program and the accompanying materials are made available under the
 terms of the Eclipse Public License v1.0 which accompanies this distribution,
 and is available at http://www.eclipse.org/legal/epl-v10.html
 -->
 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
   xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
   odl:use-default-for-reference-types="true">
  
   <reference id="dataBroker"
     interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
     odl:type="default" />
 
   <reference id="rpcRegistry"
     interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"/>'''
 
   <bean id="provider"
     class="org.opendaylight.spark.impl.HelloProvider"
     init-method="init" destroy-method="close">
     <argument ref="dataBroker" />
     <argument ref="rpcRegistry" />
  </bean>
 
 </blueprint>


Next, we add the reference to the RPC registry to the HelloProvider class and allow its injection into the class through the HelloProvider's constructor:




import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloProvider {

    private static final Logger LOG = LoggerFactory.getLogger(HelloProvider.class);

    private final DataBroker dataBroker;
    private final RpcProviderRegistry rpcProviderRegistry;

    public HelloProvider(final DataBroker dataBroker, RpcProviderRegistry rpcProviderRegistry) {
        this.dataBroker = dataBroker;
        this.rpcProviderRegistry = rpcProviderRegistry;

    }




Finally, in the HelloProvider's init() function (called when the blueprint container is created) we register the HelloService RPC with MD-SAL as follows:




 ....
    private RpcRegistration<HelloService> serviceRegistration;
    ... 

    /**
     * Method called when the blueprint container is created.
     */
    public void init() {
       serviceRegistration = rpcProviderRegistry.addRpcImplementation(HelloService.class, new HelloWorldImpl());
       LOG.info("HelloProvider Session Initiated");
    }

    /**
     * Method called when the blueprint container is destroyed.
     */
    public void close() {
       serviceRegistration.close();
       LOG.info("HelloProvider Closed");
    }




The next step is optional, however you can build just the java classes which will register the new RPC. This is useful to test the edits you have made to HelloProvider.java and HelloWorldImpl.java
In eclipse, go to hello-impl POM.xml, Run as -> Maven install
cd ../../../../../../../
mvn clean install
Return to the top level directory
cd ../
Now build the entire 'hello' again, which will pickup the changes you have made and build them into your project:
In eclipse, go to hello-aggregator POM.xml, Run as -> Maven install
mvn clean install


4.Testing the 'hello-world' RPC via REST

There are a lot of ways to test your RPC. The ones listed below are some examples.

Using the API Explorer via http.

Go to the RestConf API Documentation UI (Swagger/Open API Initiative (OAI)-based) with your web browser. You will be prompted for a username and password, by default they are admin/admin.
NOTE - in the above URL you might need to change 'localhost' to the IP/Host name to reflect your development machine's network address.
Click on
hello(2015-01-05)
and then click on
POST /operations/hello:hello-world
and provide value:
{"hello:input": { "name":"Your Name"}}
and click the button
Try it out
In the response body you should see.
{
  "output": {
    "greeting": "Hello Your Name"
  }
}


评论

此博客中的热门博文

openflow switch(I)

YANG Tools:YANG to Java Mapping

OpenDaylight架构简介