华为北向网管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_THolderimplements 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); 
}

大概返回的结果里面,我肯定百分百确定,包含了下面的这几个,

ManagedElement
EMS
EquipmentInventory
MultiLayerSubnetwork

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

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;
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/274254.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式学习第二十六天!(网络传输:TCP编程、HTTP协议)

TCP通信&#xff1a; 1. TCP发端&#xff1a; socket -> connect -> send -> recv -> close 2. TCP收端&#xff1a; socket -> bind -> listen -> accept -> recv -> send -> close 3. TCP需要用到的函数&#xff1a; 1. co…

【脚本开发】脚本的启动与暂停

文章目录 需求简单实现测试代码 更新&#xff1a;添加两个方法 需求 基于pynput库开发一个脚本。 要能够用按键控制它启动&#xff0c;暂停。 简单实现 key参数&#xff0c;代表了用什么键控制。 state属性&#xff0c;代表了当前的开关状态。 listener属性&#xff0c;是…

3.基础算法之搜索与图论

1.深度优先搜索 深度优先搜索&#xff08;DFS&#xff0c;Depth First Search&#xff09;是一种用于遍历或搜索树或图的算法。它将当前状态按照一定的规则顺序&#xff0c;先拓展一步得到一个新状态&#xff0c;再对这个新状态递归拓展下去。如果无法拓展&#xff0c;则退回…

STM32 通过Modbus协议更改内部Flash(模仿EEPROM)的运行参数

main.c测试 uint8_t uart1RxBuf[64]{0};uint8_t Adc1ConvEnd0; uint8_t Adc2ConvEnd0;int main(void) {/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initial…

【C语言刷题】——初识位操作符

【C语言刷题】——初识位操作符 位操作符介绍题一、 不创建临时变量&#xff08;第三个变量&#xff09;&#xff0c;实现两个数的交换&#xff08;1&#xff09;法一&#xff08;2&#xff09;法二 题二、 求一个数存储在内存中的二进制中“一”的个数&#xff08;1&#xff0…

【算法】Hash存储——开放寻址法

模拟散列表 维护一个集合&#xff0c;支持如下几种操作&#xff1a; I x&#xff0c;插入一个整数 x&#xff1b; Q x&#xff0c;询问整数 x是否在集合中出现过&#xff1b; 现在要进行 N次操作&#xff0c;对于每个询问操作输出对应的结果。 输入格式 第一行包含整数 N&am…

C++ 之LeetCode刷题记录(三十九)

&#x1f604;&#x1f60a;&#x1f606;&#x1f603;&#x1f604;&#x1f60a;&#x1f606;&#x1f603; 开始cpp刷题之旅。 目标&#xff1a;执行用时击败90%以上使用 C 的用户。 22. 括号生成 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用…

国产软件不背黑锅:4款强大又实用的电脑软件,用了舍不得卸载

虽然一些国产软件常被误解为“流氓、付费、广告多”&#xff0c;但实际上&#xff0c;仍有许多小众却非常优质、良心的软件被大家所忽视。 1、电脑图像工具箱 这款电脑图像工具箱堪称图片处理的瑞士军刀&#xff0c;它完全免费且无任何广告干扰。这款工具箱集成了超过一百种工…

植物病害识别:YOLO水稻病害识别数据集(11000多张,yolo标注)

YOLO水稻病害识别数据集&#xff0c;包含叶斑病&#xff0c;褐斑病&#xff0c;细菌性枯萎病&#xff0c;东格鲁病毒病4个常见病害类别&#xff0c;共11000多张图像&#xff0c;yolo标注完整&#xff0c;可直接训练。 适用于CV项目&#xff0c;毕设&#xff0c;科研&#xff0c…

物联网在智慧城市建设中的关键作用:连接、感知、智能响应

一、引言 随着信息技术的飞速发展&#xff0c;物联网&#xff08;IoT&#xff09;技术已经渗透到我们生活的方方面面&#xff0c;特别是在智慧城市建设中发挥着至关重要的作用。智慧城市是指通过运用先进的信息和通信技术&#xff0c;实现城市基础设施、公共服务、交通管理、环…

SpringSecurity原理简述

文章目录 0. 简介1. 快速入门1.1 准备工作1.2 引入SpringSecurity 2. 认证2.1 登陆校验流程2.2 原理初探2.2.1 SpringSecurity完整流程2.2.2 认证流程详解 2.3 解决问题2.3.1 思路分析2.3.2 准备工作2.3.3 实现2.3.3.1 数据库校验用户准备工作核心代码实现 2.3.3.2 密码加密存储…

微信小程序onLoad加载定义好的函数

这里小程序开发中容易犯的错误-1 给客户做一个程序。需要在页面加载的时候在onLoad(options){}中加载定义好的函数&#xff0c;代码如下 onLoad(options) {get_week_()},运行时老报错 后来修改为正确的代码 onLoad(options) {this.get_week_()//必须加this},再尝试运行&#x…

项目管理工具及模板(甘特图、OKR周报、任务管理、头脑风暴等)

项目管理常用模板大全&#xff1a; 1. 项目组OKR周报 2. 项目组传统周报工作法 3. 项目甘特图 4. 团队名单 5. 招聘跟进表 6. 出勤统计 7. 年度工作日历 8. 项目工作年计划 9. 版本排期 10. 项目组任务管理 11. 项目规划模板 12. 产品分析报告 13. 头脑风暴 信息化项目建设全套…

uniapp开发DAPP钱包应用(一) 环境搭建 Vue+ MetaMask + ABI.json

上几节我们讲了如何通过Java后端完成链上交易、信息查询、以及如何使用web3插件实现开发自测。 这一节&#xff0c;我们来说说前端DAPP的开发实现。 1. MeteMask &#x1fa9c;Java对接&#xff08;BSC&#xff09;币安链 | BNB与BEP20的开发实践&#xff08;三&#xff09;水…

做一下笔记 CXDB5CCAM-MK 与 CXDBCCAM-ML 的区别

1. CXDB5CCAM-MK 的简介 2. CXDBCCAM-ML 的简介 3. 这个两个器件的区别 最基本可见的区别是 &#xff1a; 传输速度的不同。 4. 资料在资源里面

Rust入门:Rust如何调用C静态库的函数

关于Rust调用C&#xff0c;因为接口比较复杂&#xff0c;貌似Rust不打算支持。而对于C函数&#xff0c;则相对支持较好。 如果要研究C/Rust相互关系的话&#xff0c;可以参考&#xff1a; https://docs.rs/cxx/latest/cxx/ Rust ❤️ C 这里只对调用C静态库做一个最简短的介…

uniapp 解决请求出现 /sockjs-node/info?t=问题

1. uniapp请求出现 /sockjs-node/info?t问题 1.1. 问题 uniapp项目老是出现 http://192.168.2.106:8080/sockjs-node/info?t1709704280949 1.1. sockjs-node介绍 sockjs-node 是一个JavaScript库&#xff0c;提供跨浏览器JavaScript的API&#xff0c;创建了一个低延迟、全…

(golang)切片何时会创建新切片或影响原切片

什么时候切片操作会影响原切片 // 1.切片后没有触发slice的扩容机制时 什么时候对切片操作会创建新切片不影响原切片 // 2.对切片头元素进行截取的时候 // 3.当使用append时&#xff0c;len > cap则会触发扩容机制 前置&#xff1a; //slice结构体 type SliceHeader struct…

C++ 作业 24/3/11

1、提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数&#xff08;要求使用C风格字符串完成&#xff09; #include <iostream>using namespace std;int main() {string str;cout << "please enter str:&…

不会还有人判断字符是否为数字或字母还用Ascii吧

不会还有人判断字符是否为数字或字母还用Ascii吧 c > a && c < z) || (c > 0 && c < 9当然&#xff0c;也可也用&#xff0c;下面给大家分享几个方法快速判断。 Character.isLetter(ch) 判断ch是否为字母 Character.isDigit(ch) 判断ch是否为数字…