本文源自: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:CODEodlexampleex1hello>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:CODEodlexampleex1hellohellopom.xml [INFO] Project created from Archetype in dir: D:CODEodlexampleex1hellohello [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 43.046 s [INFO] Final Memory: 21M/367M [INFO] ------------------------------------------------------------------------ D:CODEodlexampleex1hello>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:CODEodlexamplehellohellopom.xml [INFO] Project created from Archetype in dir: D:CODEodlexamplehellohello [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 'srcsitesite.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:CODEodlexamplehellohellokaraf argetassemblyin>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. 浏览器打开如下地址(adminadmin):
http://localhost:8181/apidoc/explorer/index.html
3. 测试结果
写入值,请求之后,提示成功!
也可以使用另外一种方式来测试:
http://localhost:8181/index.html