华为北向网管NCE开发教程(3)CORBA协议开发

华为北向网管NCE开发教程(1)闭坑选接口协议
华为北向网管NCE开发教程(2)REST接口开发
华为北向网管NCE开发教程(3)CORBA协议开发
华为北向网管NCE开发教程(4)(源代码+接口文档+jacorb)

完整资源
在这里插入图片描述

本文最后代码资源下图所示
在这里插入图片描述
由于一些原因,所以是需要去掉一些商业信息,这是删减后的代码接口示例,防止泄露公司信息,现在都是一些demo的示例
在这里插入图片描述
拿到代码,先修改参数信息
在这里插入图片描述

如果你真的还有选择的余地,能用REST,尽量用REST,是在没办法了,在考虑用CORBA接口吧,关键是华为写CORBA接口文档的人,是真的该死,拿去枪毙一千遍都不够,写的什么垃圾玩意。

这是我这边调用的某个性能相关的接口,然后这个接口文档里面,不告诉你怎么传参数,没一个示例,我特码怎么调接口,你说,然后只能按照代码,和接口的参数说明,当然了,参数肯定不对,所以报错了。华为那边的回复也很炸裂,不提供代码指导。不提供代码指导没毛病啊,但是特码你倒是说清楚你接口的入参是什么啊。
在这里插入图片描述

1准备工作

  1. 安装Jacorb环境(必须)
  2. IDL文件(非必须)
  3. 北向测试工具NBITestTool(强烈推荐有)(无奈,开发完我也没拿到这个工具)
  4. 开发电脑能访问网管NCE(必须)
  5. CORBA开发指南(必须)
  6. IDE支持lombok(强烈推荐有)
  7. CORBA用户指南(非必须)
  8. CORBA编程指引(非必须)

以下图为例,这是我收集到的华为提供的CORBA接口文档相关的资料,这里面有我们上面所说的IDL文件、开发指南,如果你有兴趣,你可以参考其中的开发指南,但是我说句实话,这文档放在15年前,我只能说一般般,放在今天2024年,我只能说,维护这个文档的人真该死。写的什么玩意。都不知道更新下文档的吗?
在这里插入图片描述

1.1用户指南说明

之前的文章华为北向网管NCE开发教程(2)REST接口开发中的用户指南是很有用的,因为默认的REST接口是不开启的,所以需要参照用户指南的操作去开启REST接口,但是这里CORBA的指南基本都是有的,所以不需要你在去开启。
9. 如果你是第一个采集该北向网管数据的人,我推荐你用REST,就别来折腾CORBA了
10. 如果你是第一个采集该北向网管数据的人,那么第一个人已经给你配置了CORBA接口了

1.2安装Jacorb环境(必须)

这个步骤,在《编程指引》里面有,当然,我不推荐你看那个傻逼文档。
在这里插入图片描述
安装Jacorb就是下载Jacorb,然后配置环境变量,下载地址:https://www.jacorb.org/
在这里插入图片描述
在这里插入图片描述
环境变量这样配置即可

JACORB_HOME = C:\JacORB-3.9   //以你实际解压的路径为准
path 添加  %JACORB_HOME%\bin

在这里插入图片描述
在CMD中,执行idl -h 不报错即可

idl -h

在这里插入图片描述

如果没有安装jacorb环境,直接开始运行代码(例如我给的代码),就会报错

ClassNotFoundaException: javax.rmi.CORBA.Stub

在这里插入图片描述

1.3获取IDL文件(可以跳过)

不想像个傻逼一样踩坑,你就跳过编程指引中的这节
这个只能华为那边给你们,傻逼编程指引里面,也不说一下这个IDL文件在哪,害我一顿找,这个IDL文件就是下图所示这个,不过在这里,IDL文件不是非必须得,IDL文件存在的意义,就是让你生成编写华为北向CORBA接口的Java接口代码,所以如果你能找到生成的CORBA接口的Java接口代码,就不需要IDL文件。当然咯,既然都来我博客了,我肯定就给你了,所以你不用自己去找IDL了,也不用IDL文件生成Java代码。我给你就行。
在这里插入图片描述

1.4IDL生成对应的Java代码(可以跳过)

这里我给你Java就行了,你就别去折腾了。生成的代码就是如下这个结构
在这里插入图片描述
主要是这个傻逼编程指引文档写的恶心人,对应编程指引里面的这个操作,你要按照这个操作生成jar文件,那你就是一个傻逼中的战斗机,不接受任何反驳,我当初就是这样操作的,所以我跟着傻逼了。
不想像个傻逼一样踩坑,你就别看这里这样操作,不然你也会骂人
在这里插入图片描述
这里我说一下我踩坑的细节,你们就当做看笑话就行了。我按照这个文档,一顿操作,终于生成了文档里面说的这个代码。
在这里插入图片描述
编程指引里面这样说的,反正最后那个编译并打包成成jar包NCE_idl.jar。我是看不懂。后来咨询了华为那边,华为那边A拉B进群,B说不知道,B又拉C进群,C也说不知道,然后C又拉D进群,D也不知道,D又拉E进群,最后还是F进群了以后说,给我解释,这句话的意思就是,让我把上面生成的Java文件,打包成一个jar包,然后在我的实际项目中引入这个jar包。
我只能是谁这样做,谁是大傻逼。
在这里插入图片描述
咱现在的项目基本都是Maven和gradle的,所以我准备用maven的方式来管理这个jar包,首先用mvn install把它安装到我仓库

mvn install:install-file -Dfile=D://nec_corba_huawei.jar -DgroupId=corba -DartifactId=nec-corba-huawei -Dversion=3.9.0 -Dpackaging=jar

然后在我的maven中添加依赖就可以了,当然了,这样子没问题,问题在于等到开始调用接口的时候,你就知道这么做,是一种多么傻逼的行为了
最优解,就是把生成的Java代码,直接拷贝到你的项目中去,因为我们要修改一些生成的代码

<dependency>
	<groupId>corba</groupId>
    <artifactId>nec-corba-huawei</artifactId>
    <version>3.9.0</version>
</dependency>

1.5IDE安装lombok

这个是必须的,不管你之前有没有用过lombok,在这里,你都要用lombok。理由如下
如下是编程指引里面的一段代码,这个代码什么意思,后续我会说,这个代码很重要。我想对于我们不熟悉北向网管NCE-CORBA接口开发的人,第一反应,打印这个managerNamesHolder看看。
在这里插入图片描述
很有意思的是,我们看看返回对象managerNames_THolder源代码怎么写的,是一个final的不可继承类,并且属性是共有的,也就是说我们访问属性,直接用(对象 . 属性)即可,所以不需要get和set方法,当然了toString()方法也没有。

/**
 * Generated from IDL alias "managerNames_T".
 *
 * @author JacORB IDL compiler V 3.9
 * @version generated at 2023-12-20 18:06:43
 */

public final class managerNames_THolder
	implements org.omg.CORBA.portable.Streamable
{
	public java.lang.String[] value;

	public managerNames_THolder ()
	{
	}
	public managerNames_THolder (final java.lang.String[] initial)
	{
		value = initial;
	}
	public org.omg.CORBA.TypeCode _type ()
	{
		return managerNames_THelper.type ();
	}
	public void _read (final org.omg.CORBA.portable.InputStream in)
	{
		value = managerNames_THelper.read (in);
	}
	public void _write (final org.omg.CORBA.portable.OutputStream out)
	{
		managerNames_THelper.write (out,value);
	}
}

我现在可以告诉你,现在这个CORBA接口所有接口返回的对象中,都是

  1. final不可继承
  2. 没有get/set
  3. 没有toString

那么有什么问题?

  1. 由于类不可继承,因此比如我想自己定义个类继承CORBA的对象,然后再里面附加一些属性字段这种操作是不可以的。
  2. 没有toString,你会更头疼,意味着你每次打印的时候,你打印的全是地址,比如,你调用查看机房的接口,假设给你返回了100个机房,你一打印,不好意思,全是地址信息,你打印出来的信息看不到任何有用的信息,就跟你开发用户查询的接口的时候,你后台打印了查询的这个用户对象,结果打印出来的是地址,看不到姓名,性别,年龄。
  3. 没有get/set,因为属性公有了,所以不需要get获取,不需要set设置,对象 . 属性 = "张三"就相当于set方法。但是问题来了,没有get/set,也就意味着你不能使用拷贝,不能使用Json,更不用说其他的一些列框架了。毕竟get/set都没有,Spring框架,看了都得摇头!

因此所有你查询的返回对象中,最简单的事,你直接在返回对象上面加一个注解,这样你就能避免很多的问题,然后提升你的开发效率。

@Data
public final class managerNames_THolder

2快速入门DEMO

2.1准备好的你Java项目

随便创建一个java项目,例如SpringBoot项目

2.2引入Jacorb的包

在Jacorb的安装目录的lib中,将这些包导入到你的项目中
在这里插入图片描述
项目中创建lib文件夹,然后将这些jar包复制到lib目录下
在这里插入图片描述
以STS为例,将这些jar包,引入到项目中(我尝试将他们整体打包生成一个新的jar包,然后安装到maven中,但是不起作用,无法引入,只能单个的jar包安装到maven,然后maven煮个添加)
在这里插入图片描述
这里的slf4j的两个jar包,和我项目里面的日志框架冲突了,因此这两个包就不用引入。暂时来看,没引入这两个包,不报错。
在这里插入图片描述

2.3复制生成的接口代码到你项目中

如下图所示,直接将IDL生成的Java代码拷贝到你项目中,一定是拷贝源代码,不能是引入jar包,这个包你可以按编程指引,也可以直接用我给你的。
在这里插入图片描述

2.4准备好账号密码

这里我给了一个配置文件,这个配置文件中包含

  1. 网管NCE的IP地址
  2. 网管NCE的端口
  3. 用户名
  4. 密码
    在这里插入图片描述
    然后通过Spring注入到容器中
@Data
@SpringBootConfiguration
@ConfigurationProperties(prefix = "huawei.nce.login.corba")
public class CorbaLoginReq {
	
	private String host;
	
	private String port;
	
	private String userName;
	
	private String passWord;
	
}

验证网络是否有问题

ping host
telnet host port

2.5登录NEC-CORBA

定义登录NEC返回实体CorbaLoginRes
这里因为后续我要用到当前登录所使用的orb、dynAnyFactory等对象,因此把他们整体放入到一个自定义的对象中。

@Data
public class CorbaLoginRes {
	private org.omg.CORBA.ORB orb;
	private org.omg.PortableServer.POA rootPOA ;
	private EmsSession_I emsSession;
	private DynAnyFactory dynAnyFactory;
}

登录的代码如下,可变参数只有loginReq,你不想用Spring配置文件的方式,你也可以直接代码里面写死。

注意:该方法不能连续调用,连续调用会导致EmsSession_I 为null,我们现场环境是这样的,连续登录CORBA几次以后,登录会报错,后续即使使用已经登录的EmsSession_I 也会报错,登录报错以后,只能等个五六分钟以后,才能继续用了。因此就是推荐,登录一次以后,后续就不需要登录了,用第一次登录EmsSession_I 即可。

创建类TANmsSession_IImpl继承NmsSession_IPOA

public class TANmsSession_IImpl extends NmsSession_IPOA {
	public void eventLossCleared(String endTime) {
		log("TANmsSession_IImpl.eventLossCleared(String endTime) is invoked by EMS(NCE).");
		log("endTime:"+endTime);
	}
	public void eventLossOccurred(String startTime, String notificationId) {
		log("TANmsSession_IImpl.eventLossOccurred(String startTime, String notificationId) is invoked by EMS.");
		log("startTime:"+startTime+", notificationId:"+notificationId);
	}
	public Session_I associatedSession() {
		log("TANmsSession_IImpl.associatedSession() is invoked by EMS(NCE).");
		return null;
	}
	public void endSession() {
		log("TANmsSession_IImpl.endSession() is invoked by EMS(NCE).");
	}
	public void ping() {
		log("TANmsSession_IImpl.ping() is invoked by EMS(NCE).");
	}
	private static void log(String str){
		System.out.println(str);
	}
}
@Autowired
private CorbaLoginReq loginReq;//注入配置文件中的IP,端口,用户名,密码

public CorbaLoginRes login() {
	CorbaLoginRes login = new CorbaLoginRes();
	try {
		String argv[] = new String[2];
		argv[0] = "-ORBInitRef";
		argv[1] = "NameService=corbaloc::" + loginReq.getHost() + ":" + loginReq.getPort() + "/NameService";
		org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(argv, null);
		org.omg.PortableServer.POA rootPOA;
		rootPOA = org.omg.PortableServer.POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
		rootPOA.the_POAManager().activate();
		DynAnyFactory dynAnyFactory = DynAnyFactoryHelper.narrow(orb.resolve_initial_references("DynAnyFactory"));
		org.omg.CosNaming.NamingContextExt nc = org.omg.CosNaming.NamingContextExtHelper
					.narrow(orb.resolve_initial_references("NameService"));
		org.omg.CosNaming.NameComponent[] name;
		name = new NameComponent[5];
		name[0] = new NameComponent("TMF_MTNM", "Class");
		name[1] = new NameComponent("HUAWEI", "Vendor");
		name[2] = new NameComponent("Huawei/NCE", "EmsInstance");
		name[3] = new NameComponent("2.0", "Version");
		name[4] = new NameComponent("Huawei/NCE", "EmsSessionFactory_I");
		EmsSessionFactory_I emsSessionFactory = EmsSessionFactory_IHelper.narrow(nc.resolve(name));
		NmsSession_IPOA pNmsSessionServant = new TANmsSession_IImpl();
		NmsSession_I NmsSession = pNmsSessionServant._this(orb);
		EmsSession_IHolder emsSessionInterfaceHolder = new EmsSession_IHolder();
		emsSessionFactory.getEmsSession(loginReq.getUserName(), loginReq.getPassWord(), NmsSession, emsSessionInterfaceHolder);
		EmsSession_I emsSession = emsSessionInterfaceHolder.value;
		login.setDynAnyFactory(dynAnyFactory);
		login.setOrb(orb);
		login.setRootPOA(rootPOA);
		login.setEmsSession(emsSession);
		return login;
	} catch (Exception e) {
		e.printStackTrace();
		return null;
	}
}

2.6获取所支持的管理

这个方法会返回一个字符串集合,这个具体返回的参数,这个结果值很重要。后面的开发都会用到这个结果值,如果你现在能连上网管NCE,记得把这个结果保留下来。有用。

public List<String> getAllSupportedManagers(EmsSession_I emsSession) throws ProcessingFailureException {
	managerNames_THolder managerNamesHolder = new managerNames_THolder();
	emsSession.getSupportedManagers(managerNamesHolder);
	return Arrays.asList(managerNamesHolder.value); 
}

managerNamesHolder中的内容如下。

EmsManagerName[0] CORBA_MSTP_INV
EmsManagerName[1] CORBA_MSTP_PRO
EmsManagerName[2] CORBA_MSTP_SVC
EmsManagerName[3] CORBA_MSTP_TD
EmsManagerName[4] CORBA_VPN
EmsManagerName[5] ControlPlane
EmsManagerName[6] ELLManagement
EmsManagerName[7] EMS
EmsManagerName[8] EquipmentInventory
EmsManagerName[9] FlowdomainManagement
EmsManagerName[10] GuiCutThrough
EmsManagerName[11] Maintenance
EmsManagerName[12] ManagedElement
EmsManagerName[13] MultiLayerSubnetwork
EmsManagerName[14] PerformanceManagement
EmsManagerName[15] Protection
EmsManagerName[16] SecurityManagement
EmsManagerName[17] TopoManagement
EmsManagerName[18] TrafficConditioningProfile
EmsManagerName[19] TrailNetworkProtection

2.7调用接口:获取所有的网元

在这里, 我们使用emsSession.getManage获取网元的时候,第一个参数String,固定传值ManagedElement

public List<ManagedElement_T> getAllManagedElements(EmsSession_I emsSession) {
	List<ManagedElement_T> list = null;
	try {
		Common_IHolder mgrInterface = new Common_IHolder();
		emsSession.getManager("ManagedElement", mgrInterface);
		ManagedElementMgr_I meMgr = ManagedElementMgr_IHelper.narrow(mgrInterface.value);

		ManagedElementList_THolder meListHolder = new ManagedElementList_THolder();
		ManagedElementIterator_IHolder meIteratorHolder = new ManagedElementIterator_IHolder();
		//查询100个网元
		meMgr.getAllManagedElements(100, meListHolder, meIteratorHolder);
		list = Arrays.asList(meListHolder.value);
	} catch (Exception e) {
		e.printStackTrace();
	}
	return list;
}

2.8为接口返回对象ManagedElement_T添加@Data注解

在上述我们获取所有网元的代码中,具体调用的接口

meMgr.getAllManagedElements(100, meListHolder, meIteratorHolder);

该接口的返回值是:ManagedElementList_THolder ,将其属性中的对象,子对象都为其添加@Data注解,这样就能支持Json格式化,属性拷贝,打印数据信息了。
在这里插入图片描述
例如首先我们看接口文档中,存量开发指南,找到3.4.1getAllManagedElements这个接口,这个接口说的是获取所有网元对象
在这里插入图片描述
以下我们调用该接口以后,即可使用打印,因为@Data包含了toString,看看数据是不是我们需要的数据,不是我们的数据就不用折腾了,避免数据都解析完了,然后发现接口调错了,因为有很多差不多类似功能的接口,并且每个接口返回数据可能都不一样。

meMgr.getAllManagedElements(100, meListHolder, meIteratorHolder);
			
System.out.println(meListHolder.value);

当然你也可以直接把该对象在controller层返回,因为@Data包含了toString,所以能Json格式化了。

@ApiOperation(value = "341获取所有网元")
@ApiOperationSupport(order = 5)
@PostMapping("/huawei/nce/all/ne")
public R<List<ManagedElement_T>> getAllManagedElements()  {
	EmsSession_I login = huaweiNceCorbaService.login().getEmsSession();
	List<ManagedElement_T> allNe = huaweiNceCorbaService.getAllManagedElements(login);
	return R.ok(allNe);
}

当然你也可以直接写入到文本文件中,例如如下是我自己串接的数据,然后将其格式化为Json,然后写入到本地的某个文件中。
在这里插入图片描述

3如何看懂编程指南文档

接口文档中有存量、告警、配置、性能,首先你要确定一个事,那就是你要获取什么数据,该数据在哪个开发指南里面,这里以存量为例。
在这里插入图片描述

3.1调用接口的编程模型(及其重要)

重之之重
大部分的存量接口都是按照如下方式来调用,咱们先解决大部分接口调用,个别接口在想办法研究。不敢说解决你百分之99的存量查询接口怎么调用,但是能解决你百分之95的存量接口怎么调用。后面的CORBA代码都是照着这个模板写。

//1获取指定的管理模型	必须有  
String managerName = "";
Common_IHolder commonHolder= new Common_IHolder();
emsSession.getManager(managerName, commonHolder);
<managerName>Mgr_I mgr = <managerName>Mgr_IHelper.narrow(commonHolder.value);

//2构建查询条件	非必须,部分接口不需要这个参数
NameAndStringValue_T[] query = new NameAndStringValue_T[n];
query[0] = new NameAndStringValue_T("name1", "value1");
query[1] = new NameAndStringValue_T("name2", "value2");

//3第一批返回数据量	非必须,部分接口不需要这个参数
int how_many = 200;

//4查询结果的返回对象	必须有
<managerName>_THolder res = new <managerName>_THolder();

//5返回结果的迭代对象,例如第一次查询100,然后迭代查询	非必须,某些接口查询不需要这个参数
<managerName>_Iterator_IHolder it= new <managerName>_Iterator_IHolder();
mgr.get接口方法(query, how_many , res , it);

注意这里面我画红色圈的部分,红色圈的部分,就是我们调用具体接口的时候,要更换的地方。
在这里插入图片描述

3.2案例getAllManagedElements

3.2.1确定要调用接口

这里我们以接口文档中的3.4.1getAllManagedElements为例,来讲解怎么看懂这个接口文档。
在这里插入图片描述

3.2.2获取指定的管理模型

模板代码如下,这里面,我需要知道
这个代码里面只需要替换managerName即可。问题在于我怎么知道我要用的managerName填什么?
通过我们在图中标出的3.4.1getAllManagedElements为例,3.4.1getAllManagedElements3.4 ManagedElementMgr_I章节之下,因此,这里的managerName就是ManagedElement
通过接口名看所属章节,然后根据章节名确定所用的managerName、xxxMgr_I、xxxMgr_IHelper
备注:快速入门中,获取所支持的管理getSupportedManagers接口,返回的就是全量的managerName的集合,这里验证managerName是否正确与否,就看是否存在于getSupportedManagers接口返回值中。

//代码模板  
emsSession.getManager(managerName, commonHolder);
<managerName>Mgr_I mgr = <managerName>Mgr_IHelper.narrow(commonHolder.value);

//实际代码案例1
emsSession.getManager("ManagedElement", commonHolder);
ManagedElementMgr_I mgr = ManagedElementMgr_IHelper.narrow(commonHolder.value);

//实际代码案例2
emsSession.getManager("MultiLayerSubnetwork", commonHolder);
MultiLayerSubnetworkMgr_I mgr = MultiLayerSubnetworkMgr_IHelper.narrow(commonHolder.value);

3.2.3调用方法

这里我们先说,怎么调用这个接口,再说怎么构建这个接口的参数。你肯定会问,为什么要先调用接口,再去看接口调接口的参数,这反了啊
理由就是:维护corba接口文档的这群傻逼,接口文档里面的参数,和实际的接口代码,对不上的地方多了去,要么就是代码改了,接口文档没改,要么就是代码没改,接口文档改了。
如下图所示,我们调用这个接口,然后点进去源码,看实际的参数
在这里插入图片描述

3.2.4创建接口调用参数

源代码接口如下,因此,我们就知道调用该接口的具体参数是什么了。例如该接口,只有三个参数,分别数数量、返回结果、迭代。其中输入只有数量。

void getAllManagedElements(
	int how_many,
	mtnm.tmforum.org.managedElement.ManagedElementList_THolder meList,
	mtnm.tmforum.org.managedElement.ManagedElementIterator_IHolder meIt) 
throws mtnm.tmforum.org.globaldefs.ProcessingFailureException;

然后查看接口文档,可知meList就是我们查询接口的返回值
在这里插入图片描述

3.2.5修改返回结果meList的java类

给我们的返回结果的JavaBean对象,添加@Data注解
在这里插入图片描述

3.2.3完整的调用getAllManagedElements接口

/**
  * 获取所有网元
  */
@Override
public List<ManagedElement_T> getAllManagedElements(EmsSession_I emsSession) {
	List<ManagedElement_T> list = null;
	try {
		Common_IHolder commonHolder = new Common_IHolder();
		emsSession.getManager("ManagedElement", commonHolder);
		ManagedElementMgr_I meMgr = ManagedElementMgr_IHelper.narrow(commonHolder.value);
		ManagedElementList_THolder meListHolder = new anagedElementList_THolder();
		ManagedElementIterator_IHolder meIteratorHolder = new ManagedElementIterator_IHolder();
		meMgr.getAllManagedElements(100, meListHolder, meIteratorHolder);
		System.out.println(meListHolder.value);
		list = Arrays.asList(meListHolder.value);
	} catch (Exception e) {
		e.printStackTrace();
	}
	return list;
}

3.3案例getAllEquipment

3.2.1确定要调用接口

这里我们以接口文档中的3.3.2getAllEquipment为例,来讲解

3.2.2获取指定的管理模型

在这里插入图片描述
因此下面的代码根据模板可以写出

Common_IHolder commonHolder = new Common_IHolder();
emsSession.getManager("EquipmentInventory", commonHolder);
EquipmentInventoryMgr_I mgr = EquipmentInventoryMgr_IHelper.narrow(commonHolder.value);

3.2.3调用方法

通过接口调用,找到我们实际的接口代码
在这里插入图片描述

3.2.4创建接口调用参数

查看我们的接口参数

void getAllEquipment(
	mtnm.tmforum.org.globaldefs.NameAndStringValue_T[] meOrHolderName, 
	int how_many,
	mtnm.tmforum.org.equipment.EquipmentOrHolderList_THolder eqList,
	mtnm.tmforum.org.equipment.EquipmentOrHolderIterator_IHolder eqIt) 
throws mtnm.tmforum.org.globaldefs.ProcessingFailureException;

这里对比之前,多了一个参数,这个参数类型是NameAndStringValue_T,其余的参数类型,上面已经说了,这里我就不在具体说了,就单独说这个NameAndStringValue_T参数

当然了,这里你查看接口文档说明,会发现参数名对不上,这个我之前已经吐槽很多次了,对不上的地方太多了,所以以实际的接口代码为例
例如实际代码是:NameAndStringValue_T
接口文档代码是:NamingAttributes_T
在这里插入图片描述
这里面可以看到虽然参数类型没对上,参数名称好歹对上,都叫做meOrHolderName,但是最大的问题在于,妈的,你倒是告诉我,这个meOrHolderName到底怎么传啊。eqList和eqIt都是返回值,所以我直接new一个空对象过去就可以,但是meOrHolderName是需要我自己组织数据的,但是这接口就这么牛逼,不告诉你怎么组织这个参数。翻遍了接口文档都找不到。
写了一个接口文档,不告诉你请求参数怎么组织,就问你头大不,你提了华为的工单问这接口参数怎么传,人家直接来一句,这是你代码编写的问题,你的请求还没NCE,所以不是我NCE-CORBA接口的问题
后来发现实际上接口文档里面有告诉你这个参数怎么传,只是写文档的人水平是在是无力吐槽,然后代码和接口文档也不一致。所以就找不到

接口文档搜索了下这个参数,发现还不少,就是没找到怎么用这个参数
在这里插入图片描述
这里我直接说答案吧,我也是研究了一整天的文档,然后挨个试,试出来的请求参数,这里我在接口文档的8.21章节找到一个命名规则,这里的meOrHolderName中的me就是这里的ManagedElement,当然咯,整个开发指引,开发指南,也没告诉你这个ManagedElement的请求参数,该怎么组织,目前得知就是NameAndStringValue_T的请求参数是一个数组。也就是说,我们要用下面表格中的这个举例,构建一个NameAndStringValue_T的请求参数
请求参数组织的有问题,就会报错:ProcessingFailureException:1.0

mtnm.tmforum.org.globaldefs.ProcessingFailureException: IDL:mtnm.tmforum.org/globaldefs/ProcessingFailureException:1.0

在这里插入图片描述
在我经过九九八十一的困难测试以后,终于试出了怎么去组织这个参数

NameAndStringValue_T[] query = new NameAndStringValue_T[2];
query[0] = new NameAndStringValue_T("EMS", "Huawei/NCE");
query[1] = new NameAndStringValue_T("ManagedElement", "网元ID");

网元ID就是我们之前查询所有网元接口时,里面的name属性的第二个元素的value值。
当时也是看到这个接口的参数,结合8.21才想着应该是这样传参数
在这里插入图片描述

3.2.5修改返回结果meList的java类

按照之前的操作,给返回结果的对象加上@Data注解

3.2.3完整的调用getAllManagedElements接口

/**
  * 获取指定网元的所有设备
  */
@Override
public List<EquipmentOrHolder_T> getAllEquipment(EmsSession_I emsSession, String stElement) throws ProcessingFailureException {
	List<EquipmentOrHolder_T> list = null;
	Common_IHolder commonHolder = new Common_IHolder();
	emsSession.getManager("EquipmentInventory", commonHolder);
	EquipmentInventoryMgr_I mgr = EquipmentInventoryMgr_IHelper.narrow(commonHolder.value);
	NameAndStringValue_T[] query = new NameAndStringValue_T[2];
	query[0] = new NameAndStringValue_T("EMS", "Huawei/NCE");
	query[1] = new NameAndStringValue_T("ManagedElement", stElement);
	EquipmentOrHolderList_THolder eqList = new EquipmentOrHolderList_THolder();
	EquipmentOrHolderIterator_IHolder eqIt = new EquipmentOrHolderIterator_IHolder();
	mgr.getAllEquipment(query, 200, eqList, eqIt);
	list = Arrays.asList(eqList.value);
	return list;
}

4关于查询参数怎么构建

有些接口参数中是需要组装请求参数的,对于返回参数,咱们不用管,直接new一个空对象就可,但是有些请求参数不允许为空的时候,就需要我们自己去构建请求参数,接口文档并没有告知怎么来构建请求参数,这里就分享我的一些经验

4.1getContainedEquipment

以这个为例,我们接口中找到这个输入参数,equipmentHolder,然后再第八章节中,找到和这个有关的参数模型名字一样的,找不到名字一样的话,就只能连蒙带猜了。
在这里插入图片描述
这个接口入参叫做:equipmentHolder
第八章节的模型叫做:EquipmentHolder
所以,这个名字起码还对上了
在这里插入图片描述
接着你在看我实际代码的请求参数这样组织的

@Override
public List<EquipmentOrHolder_T> getContainedEquipment(EmsSession_I emsSession, String stElement, String EquipmentHolder) throws ProcessingFailureException {
	List<EquipmentOrHolder_T> list = null;
	Common_IHolder commonHolder = new Common_IHolder(); 
	emsSession.getManager("EquipmentInventory", commonHolder); 
	EquipmentInventoryMgr_I eiMgr = EquipmentInventoryMgr_IHelper.narrow(commonHolder.value);
	EquipmentOrHolderList_THolder listHolder = new EquipmentOrHolderList_THolder();
	NameAndStringValue_T[] equipmentHolderName = new NameAndStringValue_T[3];
	/**
	 * 1.name="EMS"; value="Huawei/NCE"
	   2.name="ManagedElement";value="33554433"
	   3.name="EquipmentHolder";value="/rack=1/shelf=590225/slot=1"
	 */
	equipmentHolderName[0] = new NameAndStringValue_T("EMS", "Huawei/NCE");
	equipmentHolderName[1] = new NameAndStringValue_T("ManagedElement", stElement);
	equipmentHolderName[2] = new NameAndStringValue_T("EquipmentHolder", EquipmentHolder);
	eiMgr.getContainedEquipment(equipmentHolderName,listHolder);
	list = Arrays.asList(listHolder.value);
	return list;
}

4.2getAllSupportedPTPs

同理,接口文档的输入参数是:equipmentName
在这里插入图片描述
在第八章,我们没有找到equipmentName,但是找到Equipment,所以说,这个名字,特码的,不一定对得上。看到这里,你就说写这个文档的人,该不该拖出去枪毙三分钟吧
在这里插入图片描述
当然,还能结合就是之前抓取的报文数据来猜这个参数长什么样
在这里插入图片描述
根据Equipment的模型或者之前返回的一些报文,组织请求参数

@Override
public List<TerminationPoint_T> getAllSupportedPTPs(EmsSession_I emsSession, String stElement, String equipmentHolder, String equipment) throws ProcessingFailureException {
	List<TerminationPoint_T> list = null;
	Common_IHolder commonHolder = new Common_IHolder(); 
	emsSession.getManager("EquipmentInventory", commonHolder); 
	EquipmentInventoryMgr_I eiMgr = EquipmentInventoryMgr_IHelper.narrow(commonHolder.value);
	NameAndStringValue_T[] query = new NameAndStringValue_T[4];
	query[0] = new NameAndStringValue_T("EMS", "Huawei/NCE");
	query[1] = new NameAndStringValue_T("ManagedElement", stElement);
	query[2] = new NameAndStringValue_T("EquipmentHolder", equipmentHolder);
	query[3] = new NameAndStringValue_T("Equipment", equipment);
	TerminationPointList_THolder listHolder = new TerminationPointList_THolder();
	TerminationPointIterator_IHolder itHolder = new TerminationPointIterator_IHolder();
	eiMgr.getAllSupportedPTPs(query, 100, listHolder, itHolder);
	list = Arrays.asList(listHolder.value);
	return list;
}

好了,基本到这里就差不多了

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值