本文源自:https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Startup_Project_Archetype part2
一、構建Hello項目
1. 執行構建項目命令:
mvn archetype:generate -DarchetypeGroupId=org.opendaylight.controller -DarchetypeArtifactId=opendaylight-startup-archetype -DarchetypeRepository=http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/ -DarchetypeCatalog=http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/archetype-catalog.xml
提示如下信息:
[INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Maven Stub Project (No POM) 1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] >>> maven-archetype-plugin:3.0.1:generate (default-cli) > generate-sources @ standalone-pom >>> [INFO] [INFO] <<< maven-archetype-plugin:3.0.1:generate (default-cli) < generate-sources @ standalone-pom <<< [INFO] [INFO] --- maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom --- [INFO] Generating project in Interactive mode [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.031 s [INFO] Finished at: 2017-07-25T18:53:36+08:00 [INFO] Final Memory: 14M/245M [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:3.0.1:generate (default-cli) on project standalone-pom: archetypeCatalog 'http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/archetype-catalog.xml' is not supported anymore. Please read the plugin documentation for details. -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
搜索未找到答案,使用Example部分的命令:
mvn archetype:generate -DarchetypeGroupId=org.opendaylight.controller -DarchetypeArtifactId=opendaylight-startup-archetype -DarchetypeRepository=http://nexus.opendaylight.org/content/repositories/opendaylight.release -DarchetypeCatalog=remote -DarchetypeVersion=1.3.0-Carbon
輸入交互信息:
Define value for property 'groupId': org.opendaylight.hello Define value for property 'artifactId': hello [INFO] Using property: version = 0.1.0-SNAPSHOT Define value for property 'package' org.opendaylight.hello: : Define value for property 'classPrefix' Hello: : hello Define value for property 'copyright': No [INFO] Using property: copyrightYear = 2017 Confirm properties configuration: groupId: org.opendaylight.hello artifactId: hello version: 0.1.0-SNAPSHOT package: org.opendaylight.hello classPrefix: hello copyright: No copyrightYear: 2017 Y: : Y
或者: 根據 opendaylight-startup-archetype在nexus私服(https://nexus.opendaylight.org)查詢的坐標信息:
<dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>opendaylight-startup-archetype</artifactId> <version>1.3.0-Carbon</version> </dependency>
D:\CODE\odlexample\ex1hello>mvn archetype:generate -DarchetypeGroupId=org.opendaylight.controller -DarchetypeArtifactId=opendaylight-startup-archetype -DarchetypeVersion=1.3.0-Carbon [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Maven Stub Project (No POM) 1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] >>> maven-archetype-plugin:3.0.1:generate (default-cli) > generate-sources @ standalone-pom >>> [INFO] [INFO] <<< maven-archetype-plugin:3.0.1:generate (default-cli) < generate-sources @ standalone-pom <<< [INFO] [INFO] --- maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom --- [INFO] Generating project in Interactive mode [WARNING] Archetype not found in any catalog. Falling back to central repository. [WARNING] Add a repsoitory with id 'archetype' in your settings.xml if archetype's repository is elsewhere. Define value for property 'groupId': org.opendaylight.hello Define value for property 'artifactId': hello [INFO] Using property: version = 0.1.0-SNAPSHOT Define value for property 'package' org.opendaylight.hello: : Define value for property 'classPrefix' Hello: : Hello Define value for property 'copyright': no [INFO] Using property: copyrightYear = 2017 Confirm properties configuration: groupId: org.opendaylight.hello artifactId: hello version: 0.1.0-SNAPSHOT package: org.opendaylight.hello classPrefix: Hello copyright: no copyrightYear: 2017 Y: : y [INFO] ---------------------------------------------------------------------------- [INFO] Using following parameters for creating project from Archetype: opendaylight-startup-archetype:1.3.0-Carbon [INFO] ---------------------------------------------------------------------------- [INFO] Parameter: groupId, Value: org.opendaylight.hello [INFO] Parameter: artifactId, Value: hello [INFO] Parameter: version, Value: 0.1.0-SNAPSHOT [INFO] Parameter: package, Value: org.opendaylight.hello [INFO] Parameter: packageInPathFormat, Value: org/opendaylight/hello [INFO] Parameter: classPrefix, Value: Hello [INFO] Parameter: package, Value: org.opendaylight.hello [INFO] Parameter: version, Value: 0.1.0-SNAPSHOT [INFO] Parameter: copyright, Value: no [INFO] Parameter: groupId, Value: org.opendaylight.hello [INFO] Parameter: artifactId, Value: hello [INFO] Parameter: copyrightYear, Value: 2017 [WARNING] Don't override file D:\CODE\odlexample\ex1hello\hello\pom.xml [INFO] Project created from Archetype in dir: D:\CODE\odlexample\ex1hello\hello [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 43.046 s [INFO] Final Memory: 21M/367M [INFO] ------------------------------------------------------------------------ D:\CODE\odlexample\ex1hello>tree /f D:. └─hello │ .gitignore │ .gitreview │ deploy-site.xml │ pom.xml │ ├─api │ │ pom.xml │ │ │ └─src │ └─main │ └─yang │ hello.yang │ ├─artifacts │ pom.xml │ ├─cli │ │ pom.xml │ │ │ └─src │ └─main │ ├─java │ │ └─org │ │ └─opendaylight │ │ └─hello │ │ └─cli │ │ ├─api │ │ │ HelloCliCommands.java │ │ │ │ │ ├─commands │ │ │ HelloCliTestCommand.java │ │ │ │ │ └─impl │ │ HelloCliCommandsImpl.java │ │ │ └─resources │ └─org │ └─opendaylight │ └─blueprint │ cli-blueprint.xml │ ├─features │ │ pom.xml │ │ │ └─src │ └─main │ └─features │ features.xml │ ├─impl │ │ pom.xml │ │ │ └─src │ ├─main │ │ ├─java │ │ │ └─org │ │ │ └─opendaylight │ │ │ └─hello │ │ │ └─impl │ │ │ HelloProvider.java │ │ │ │ │ └─resources │ │ └─org │ │ └─opendaylight │ │ └─blueprint │ │ impl-blueprint.xml │ │ │ └─test │ └─java ├─it │ │ pom.xml │ │ │ └─src │ └─test │ └─java │ └─org │ └─opendaylight │ └─hello │ └─it │ HelloIT.java │ ├─karaf │ pom.xml │ └─src ├─main │ └─resources │ stylesheet.css │ └─site site.xml
2. 成功后執行如下信息:
[INFO] ---------------------------------------------------------------------------- [INFO] Using following parameters for creating project from Archetype: opendaylight-startup-archetype:1.3.0-Carbon [INFO] ---------------------------------------------------------------------------- [INFO] Parameter: groupId, Value: org.opendaylight.hello [INFO] Parameter: artifactId, Value: hello [INFO] Parameter: version, Value: 0.1.0-SNAPSHOT [INFO] Parameter: package, Value: org.opendaylight.hello [INFO] Parameter: packageInPathFormat, Value: org/opendaylight/hello [INFO] Parameter: classPrefix, Value: hello [INFO] Parameter: package, Value: org.opendaylight.hello [INFO] Parameter: version, Value: 0.1.0-SNAPSHOT [INFO] Parameter: copyright, Value: No [INFO] Parameter: groupId, Value: org.opendaylight.hello [INFO] Parameter: artifactId, Value: hello [INFO] Parameter: copyrightYear, Value: 2017 [WARNING] Don't override file D:\CODE\odlexample\hello\hello\pom.xml [INFO] Project created from Archetype in dir: D:\CODE\odlexample\hello\hello [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 45.526 s
3. 構建Hello項目:
mvn clean install -Dmaven.test.failure.ignore=true
成功后提示如下信息:
[INFO] --- maven-site-plugin:3.6:attach-descriptor (generate-site) @ hello-aggregator --- [INFO] Attaching 'src\site\site.xml' site descriptor with classifier 'site'. [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] [INFO] ODL :: org.opendaylight.hello :: hello-api ......... SUCCESS [ 19.565 s] [INFO] ODL :: org.opendaylight.hello :: hello-impl ........ SUCCESS [ 8.826 s] [INFO] ODL :: org.opendaylight.hello :: hello-cli ......... SUCCESS [ 8.878 s] [INFO] ODL :: org.opendaylight.hello :: hello-features .... SUCCESS [15:41 min] [INFO] ODL :: org.opendaylight.hello :: hello-karaf ....... SUCCESS [ 41.676 s] [INFO] ODL :: org.opendaylight.hello :: hello-artifacts ... SUCCESS [ 1.794 s] [INFO] ODL :: org.opendaylight.hello :: hello-it .......... SUCCESS [03:38 min] [INFO] hello .............................................. SUCCESS [ 23.209 s] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 21:07 min
對應features.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- vi: set et smarttab sw=4 tabstop=4: --> <!-- Copyright © 2017 No 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 --> <features name="odl-hello-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> <repository>mvn:org.opendaylight.yangtools/features-yangtools/{{VERSION}}/xml/features</repository> <repository>mvn:org.opendaylight.controller/features-mdsal/{{VERSION}}/xml/features</repository> <repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/{{VERSION}}/xml/features</repository> <repository>mvn:org.opendaylight.netconf/features-restconf/{{VERSION}}/xml/features</repository> <repository>mvn:org.opendaylight.dluxapps/features-dluxapps/{{VERSION}}/xml/features</repository> <feature name='odl-hello-api' version='${project.version}' description='OpenDaylight :: hello :: api'> <feature version='${mdsal.model.version}'>odl-mdsal-models</feature> <bundle>mvn:org.opendaylight.hello/hello-api/{{VERSION}}</bundle> </feature> <feature name='odl-hello' version='${project.version}' description='OpenDaylight :: hello'> <feature version='${mdsal.version}'>odl-mdsal-broker</feature> <feature version='${project.version}'>odl-hello-api</feature> <bundle>mvn:org.opendaylight.hello/hello-impl/{{VERSION}}</bundle> </feature> <feature name='odl-hello-rest' version='${project.version}' description='OpenDaylight :: hello :: REST'> <feature version="${project.version}">odl-hello</feature> <feature version="${restconf.version}">odl-restconf</feature> </feature> <feature name='odl-hello-ui' version='${project.version}' description='OpenDaylight :: hello :: UI'> <feature version="${project.version}">odl-hello-rest</feature> <feature version="${restconf.version}">odl-mdsal-apidocs</feature> <feature version="${dluxapps.version}">odl-dluxapps-yangman</feature> </feature> <feature name='odl-hello-cli' version='${project.version}' description='OpenDaylight :: hello :: CLI'> <feature version="${project.version}">odl-hello</feature> <bundle>mvn:org.opendaylight.hello/hello-cli/{{VERSION}}</bundle> </feature> </features>
查看基本功能、關閉OpenDaylight與上文同;
二、增加簡單的Helloworld RPC API
1. 編輯 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; } } } }
2. 執行
mvn clean install -Dmaven.test.failure.ignore=true
成功顯示如下信息:
[INFO] Reactor Summary: [INFO] [INFO] ODL :: org.opendaylight.hello :: hello-api ......... SUCCESS [ 22.707 s] [INFO] ODL :: org.opendaylight.hello :: hello-impl ........ SUCCESS [ 10.392 s] [INFO] ODL :: org.opendaylight.hello :: hello-cli ......... SUCCESS [ 9.901 s] [INFO] ODL :: org.opendaylight.hello :: hello-features .... SUCCESS [15:43 min] [INFO] ODL :: org.opendaylight.hello :: hello-karaf ....... SUCCESS [ 35.899 s] [INFO] ODL :: org.opendaylight.hello :: hello-artifacts ... SUCCESS [ 1.349 s] [INFO] ODL :: org.opendaylight.hello :: hello-it .......... SUCCESS [03:37 min] [INFO] hello .............................................. SUCCESS [ 23.311 s] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 21:07 min
到目前生成的類
helloProvider.java:作為服務提供者,后續將綁定helloService及其實現Impl.
/* * Copyright © 2017 No 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 */ package org.opendaylight.hello.impl; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class helloProvider { private static final Logger LOG = LoggerFactory.getLogger(helloProvider.class); private final DataBroker dataBroker; public helloProvider(final DataBroker dataBroker) { this.dataBroker = dataBroker; } /** * Method called when the blueprint container is created. */ public void init() { LOG.info("helloProvider Session Initiated"); } /** * Method called when the blueprint container is destroyed. */ public void close() { LOG.info("helloProvider Closed"); } }
helloService.java
package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hello.rev150105; import org.opendaylight.yangtools.yang.binding.RpcService; import org.opendaylight.yangtools.yang.common.RpcResult; import java.util.concurrent.Future; /** * Interface for implementing the following YANG RPCs defined in module <b>hello</b> * <pre> * rpc hello-world { * input { * leaf name { * type string; * } * } * * output { * leaf greeting { * type string; * } * } * } * </pre> * */ public interface HelloService extends RpcService { Future<RpcResult<HelloWorldOutput>> helloWorld(HelloWorldInput input); }
impl-blueprint.xml內容:
<?xml version="1.0" encoding="UTF-8"?> <!-- vi: set et smarttab sw=4 tabstop=4: --> <!-- Copyright © 2017 No 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" /> <bean id="provider" class="org.opendaylight.hello.impl.helloProvider" init-method="init" destroy-method="close"> <argument ref="dataBroker" /> </bean> </blueprint>
在 Blueprint XML 中,bean
元素將定義一個 bean 管理器。用於對象構造的參數由 argument
元素指定;注入的屬性則由 property
子元素指定。
property
元素指定要注入的屬性的名稱和值。屬性名與 Java 類中的 setter 方法名對應。例如,如果屬性名為 foo
,那么對應的 setter 方法為 setFoo(arg)
。屬性名和對應的 setter 方法名遵循 JavaBeans 規范中定義的屬性設計模式。
詳細信息可參考:https://www.ibm.com/developerworks/cn/opensource/os-osgiblueprint/
3. 實現RPC API:創建HelloWorldImpl.java(目錄:impl/src/main/java/org/opendaylight/hello/impl)
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(); } }
4. 綁定MD-SAL
(1). 在文件impl-blueprint.xml( src/main/resources/org/opendaylight/blueprint)注冊RPC引用,增加粗體部分
<?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>
(2). 類HelloProvider注入DataBroker和RPCProviderRegistry
(3). 類HelloProvider中init方法中綁定HelloService和HelloWorldImpl
private RpcRegistration<HelloService> serviceRegistration; public HelloProvider(final DataBroker dataBroker, RpcProviderRegistry rpcProviderRegistry) { this.dataBroker = dataBroker; this.rpcProviderRegistry = rpcProviderRegistry; } /** * 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"); }
三、測試
1. 啟動OpenDayLight
D:\CODE\odlexample\hello\hello\karaf\target\assembly\bin>karaf Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=256M; support was removed in 8.0 Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=512M; support was removed in 8.0 Apache Karaf starting up. Press Enter to open the shell now... 100% [========================================================================] Karaf started in 29s. Bundle stats: 294 active, 294 total ________ ________ .__ .__ .__ __ \_____ \ ______ ____ ____ \______ \ _____ ___.__.| | |__| ____ | |___/ |_ / | \\____ \_/ __ \ / \ | | \\__ \< | || | | |/ ___\| | \ __\ / | \ |_> > ___/| | \| ` \/ __ \\___ || |_| / /_/ > Y \ | \_______ / __/ \___ >___| /_______ (____ / ____||____/__\___ /|___| /__| \/|__| \/ \/ \/ \/\/ /_____/ \/ Hit '<tab>' for a list of available commands and '[cmd] --help' for help on a specific command. Hit '<ctrl-d>' or type 'system:shutdown' or 'logout' to shutdown OpenDaylight. opendaylight-user@root>
2. 瀏覽器打開如下地址(admin\admin):
http://localhost:8181/apidoc/explorer/index.html
3. 測試結果
寫入值,請求之后,提示成功!
也可以使用另外一種方式來測試:
http://localhost:8181/index.html