1 Developing Apps on the OpenDaylight controller
2 ==============================================
4 This section provides information that is required to develop apps on
5 the OpenDaylight controller.
7 You can either develop apps within the controller using the model-driven
8 SAL (MD-SAL) archetype or develop external apps and use the RESTCONF to
9 communicate with the controller.
14 This section enables you to get started with app development within the
15 OpenDaylight controller. In this example, you perform the following
16 steps to develop an app.
18 1. Create a local repository for the code using a simple build process.
20 2. Start the OpenDaylight controller.
22 3. Test a simple remote procedure call (RPC) which you have created
23 based on the principle of *hello world*.
28 This example requires the following.
30 - A development environment with following set up and working correctly
33 - Maven 3.1.1 or later
35 - Java 7- or Java 8-compliant JDK
37 - An appropriate Maven settings.xml file. A simple way to get the
38 default OpenDaylight settings.xml file is:
42 cp -n ~/.m2/settings.xml{,.orig} ; wget -q -O - https://raw.githubusercontent.com/opendaylight/odlparent/master/settings.xml > ~/.m2/settings.xml
46 If you are using Linux or Mac OS X as your development OS, your
47 local repository is ~/.m2/repository. For other platforms the local
48 repository location will vary.
50 Building an example module
51 --------------------------
53 To develop an app perform the following steps.
55 1. Create an *Example* project using Maven and an archetype called the
56 *opendaylight-startup-archetype*. If you are downloading this project
57 for the first time, then it will take sometime to pull all the code
58 from the remote repository.
62 mvn archetype:generate -DarchetypeGroupId=org.opendaylight.controller -DarchetypeArtifactId=opendaylight-startup-archetype \
63 -DarchetypeRepository=https://nexus.opendaylight.org/content/repositories/<opendaylight.release | opendaylight.snapshot>/ \
64 -DarchetypeCatalog=remote -DarchetypeVersion=<Archetype-Version>
66 To find the correct <Archetype-Version> for an OpenDaylight release, search https://nexus.opendaylight.org for the
67 ``archetypeArtifactId`` (e.g. ``https://nexus.opendaylight.org/#nexus-search;quick~opendaylight-startup-archetype``); and if it's a
68 ``*-SNAPSHOT`` then use ``-DarchetypeRepository=https://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/``, otherwise
69 use ``-DarchetypeRepository=https://nexus.opendaylight.org/content/repositories/opendaylight.release/``.
71 2. Update the properties values as follows. Ensure that the groupid and
72 the artifactid is lower case.
76 Define value for property 'groupId': : org.opendaylight.example
77 Define value for property 'artifactId': : example
78 Define value for property 'version': 1.0-SNAPSHOT: : 1.0.0-SNAPSHOT
79 Define value for property 'package': org.opendaylight.example: :
80 Define value for property 'classPrefix': ${artifactId.substring(0,1).toUpperCase()}${artifactId.substring(1)}
81 Define value for property 'copyright': : Copyright (c) 2015 Yoyodyne, Inc.
83 3. Accept the default value of classPrefix that is,
84 ``(${artifactId.substring(0,1).toUpperCase()}${artifactId.substring(1)})``.
85 The classPrefix creates a Java Class Prefix by capitalizing the first
86 character of the artifactId.
90 In this scenario, the classPrefix used is "Example". Create a
91 top-level directory for the archetype.
105 4. Build the *example* project.
109 Depending on your development machine’s specification this might
110 take a little while. Ensure that you are in the project’s root
111 directory, example/, and then issue the build command, shown
118 5. Start the *example* project for the first time.
122 cd karaf/target/assembly/bin
126 6. Wait for the karaf cli that appears as follows. Wait for OpenDaylight
127 to fully load all the components. This can take a minute or two after
128 the prompt appears. Check the CPU on your dev machine, specifically
129 the Java process to see when it calms down.
133 opendaylight-user@root>
135 7. Verify if the “example” module is built and search for the log entry
136 which includes the entry *ExampleProvider Session Initiated*.
140 log:display | grep Example
142 8. Shutdown the OpenDaylight through the console by using the following
149 Defining a Simple Hello World RPC
150 ---------------------------------
152 1. | Run the maven archetype *opendaylight-startup-archetype*, and
153 create the *hello* project.
157 mvn archetype:generate -DarchetypeGroupId=org.opendaylight.controller -DarchetypeArtifactId=opendaylight-startup-archetype \
158 -DarchetypeRepository=http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/ \
159 -DarchetypeCatalog=http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/archetype-catalog.xml
161 2. Update the Properties values as follows.
165 Define value for property 'groupId': : org.opendaylight.hello
166 Define value for property 'artifactId': : hello
167 Define value for property 'version': 1.0-SNAPSHOT: : 1.0.0-SNAPSHOT
168 Define value for property 'package': org.opendaylight.hello: :
169 Define value for property 'classPrefix': ${artifactId.substring(0,1).toUpperCase()}${artifactId.substring(1)}
170 Define value for property 'copyright': : Copyright(c) Yoyodyne, Inc.
172 3. View the *hello* project.
185 4. Build *hello* project by using the following command.
191 5. Verify that the project is functioning by executing karaf.
195 cd karaf/target/assembly/bin
198 6. | The karaf cli appears as follows.
199 | NOTE: Remember to wait for OpenDaylight to load completely. Verify
200 that the Java process CPU has stabilized.+
204 opendaylight-user@root>
206 7. Verify that the *hello* module is loaded by checking the log.
210 log:display | grep Hello
218 9. Return to the top of the directory structure:
224 10. View the entry point to understand where the log line came from. The
225 entry point is in the impl project:
229 impl/src/main/java/org/opendaylight/hello/impl/HelloProvider.java
231 11. Add any new things that you are doing in your implementation by
232 using the HelloProvider.onSessionInitiate method. Its analogous to
238 public void onSessionInitiated(ProviderContext session) {
239 LOG.info("HelloProvider Session Initiated");
242 Add a simple HelloWorld RPC API
243 -------------------------------
245 1. Navigate to the file.
250 api/src/main/yang/hello.yang
252 2. Edit this file as follows. In the following example, we are adding
253 the code in a YANG module to define the *hello-world* RPC:
259 namespace "urn:opendaylight:params:xml:ns:yang:hello";
261 revision "2015-01-05" {
262 description "Initial revision of hello model";
278 3. Return to the hello/api directory and build your API as follows.
285 Implement the HelloWorld RPC API
286 --------------------------------
288 1. Define the HelloService, which is invoked through the *hello-world*
293 cd ../impl/src/main/java/org/opendaylight/hello/impl/
295 2. Create a new file called HelloWorldImpl.java and add in the code
300 package org.opendaylight.hello.impl;
301 import java.util.concurrent.Future;
302 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloService;
303 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldInput;
304 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldOutput;
305 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloWorldOutputBuilder;
306 import org.opendaylight.yangtools.yang.common.RpcResult;
307 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
308 public class HelloWorldImpl implements HelloService {
310 public Future<RpcResult<HelloWorldOutput>> helloWorld(HelloWorldInput input) {
311 HelloWorldOutputBuilder helloBuilder = new HelloWorldOutputBuilder();
312 helloBuilder.setGreating("Hello " + input.getName());
313 return RpcResultBuilder.success(helloBuilder.build()).buildFuture();
317 3. The HelloProvider.java file is in the current directory. Register the
318 RPC that you created in the *hello.yang* file in the
319 HelloProvider.java file. You can either edit the HelloProvider.java
320 to match what is below or you can simple replace it with the code
326 * Copyright(c) Yoyodyne, Inc. and others. All rights reserved.
328 * This program and the accompanying materials are made available under the
329 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
330 * and is available at http://www.eclipse.org/legal/epl-v10.html
332 package org.opendaylight.hello.impl;
334 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
335 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
336 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
337 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105.HelloService;
338 import org.slf4j.Logger;
339 import org.slf4j.LoggerFactory;
341 public class HelloProvider implements BindingAwareProvider, AutoCloseable {
342 private static final Logger LOG = LoggerFactory.getLogger(HelloProvider.class);
343 private RpcRegistration<HelloService> helloService;
345 public void onSessionInitiated(ProviderContext session) {
346 LOG.info("HelloProvider Session Initiated");
347 helloService = session.addRpcImplementation(HelloService.class, new HelloWorldImpl());
350 public void close() throws Exception {
351 LOG.info("HelloProvider Closed");
352 if (helloService != null) {
353 helloService.close();
358 4. Optionally, you can also build the Java classes which will register
359 the new RPC. This is useful to test the edits you have made to
360 HelloProvider.java and HelloWorldImpl.java.
364 cd ../../../../../../../
367 5. Return to the top level directory
373 6. Build the entire *hello* again, which will pickup the changes you
374 have made and build them into your project:
380 Execute the *hello* project for the first time
381 ----------------------------------------------
387 cd ../karaf/target/assembly/bin
390 2. Wait for the project to load completely. Then view the log to see the
391 loaded *Hello* Module:
395 log:display | grep Hello
397 Test the *hello-world* RPC via REST
398 -----------------------------------
400 There are a lot of ways to test your RPC. Following are some examples.
402 1. Using the API Explorer through HTTP
404 2. Using a browser REST client
406 Using the API Explorer through HTTP
407 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
409 1. | Navigate to `apidoc
410 UI <http://localhost:8181/apidoc/explorer/index.html>`__ with your
412 | NOTE: In the URL mentioned above, Change *localhost* to the IP/Host
413 name to reflect your development machine’s network address.
425 POST /operations/hello:hello-world
427 4. Provide the required value.
431 {"hello:input": { "name":"Your Name"}}
435 6. Enter the username and password, by default the credentials are
438 7. In the response body you should see.
444 "greating": "Hello Your Name"
448 Using a browser REST client
449 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
451 | For example, use the following information in the Firefox plugin
453 [`https://github.com/chao/RESTClient} <https://github.com/chao/RESTClient}>`__
457 POST: http://192.168.1.43:8181/restconf/operations/hello:hello-world
477 If you get a response code 501 while attempting to POST
478 /operations/hello:hello-world, check the file: HelloProvider.java and
479 make sure the helloService member is being set. By not invoking
480 "session.addRpcImplementation()" the REST API will be unable to map
481 /operations/hello:hello-world url to HelloWorldImpl.