一、jar包信息
其他地区的同事开发的模块,依赖该jar包用于cli-name转换,暂且叫它A.jar。
该模块基于dropwizard框架,内部依赖比较复杂。
依赖A.jar后,调试过程中产生了不少问题,做个记录,有些解决方案比较蠢。
二、springboot依赖该jar包,问题记录
1. IDEA中运行junit单元测试,报错:command line is too long
一般情况下可采用的解决方案 : https://blog.csdn.net/kzadmxz/article/details/80322687
但是依赖的这个jar包中,cli-name转换流程,有获取classpath,扫描jar包中的xml文件这个逻辑
String javaClassPath = System.getProperty("java.class.path");
dynamic classpath造成获取到的classpath不正确,扫描不到xml文件,产生的问题类似这个:https://blog.csdn.net/moneyshi/article/details/82459039
最终解决“command line is too long”的方法还是要使本地存储库的路径尽可能短,参考 http://www.it1352.com/535521.html
2. Application Run failed
A.jar基于dropwizard框架,应用启动失败可能是dropwizard的一些注解的影响或者引入了冲突的jar包,具体原因没有深究。
对A.jar做了依赖分析,排除掉其中的xxx-xx-rest,应用可正常启动
com.xxx.xxx.xxx.platform
xx-xx-xxconverthelper
xxxxx
com.xxx.xxx.xx.platform
xxx-xx-rest
3. 框架不兼容
前面提到依赖的这个jar,它是基于dropwizard框架下的一个module,默认的IOC容器为hk2,其中有个类中存在这样的代码:
serviceLocator = ServiceLocatorHolder.getLocator();
inventoryLtpService = (InventoryLtpService)serviceLocator.getService(InventoryLtpService.class, new Annotation[0]);
我们是springboot框架,用的是springboot的IOC,hk2的serviceLocator必然是获取不到的,上面的代码会报空指针异常。
没有想到什么更好的方案,采用的解决方法是覆盖jar包中的这个类,重新实现代码逻辑。可参考:https://blog.csdn.net/u013062329/article/details/86592385
三、osgi依赖该jar包,问题记录
1. jar包冲突
运行UT,报错,查找到log4j-over-slf4j是由umben-em-rest间接引入的,直接全部排除掉umben-em-rest,同2.2
2. osgi依赖第三方非bundle的jar包
umebn-em-rosngconverthelper是一个普通的jar包,非bundle。参考https://blog.csdn.net/sunquan291/article/details/89189318
采用的解决方案是第三方依赖作成JAR,嵌入到当前bundle中。存在的问题是A.jar提供的cli-name转换功能,里面依赖了比较多其他jar包,需要一起嵌入进来,依赖传递问题比较严重,调试起来复杂,还有import-package的处理需要比较仔细。
对于依赖传递问题,一开始是做了依赖分析,想尽量把依赖都嵌入进来,避免调试时一遍遍出现ClassDefNotFound。但是一些错误引入会造成一些麻烦,比如我把jdom错误地作为依赖写在了pom里,造成
bundle安装时报错,直到看到 https://stackoverflow.com/questions/33395100/the-default-package-is-not-permitted-by-the-import-package-syntax 最后一个回答,才意识到错误所在。尽量还是只嵌入代码逻辑需要用到的jar包,一来避免类似这样的低级错误,二来尽量减小bundle的体积。
3. classpath问题
上面提到cli-name转换流程,有获取classpath,扫描jar包中的xml文件这个逻辑。当运行karaf时,debug到 System.getProperty("java.class.path") 这一步,无法获取到JDK目录下的lib jar包,因此无法找到xml文件。https://stackoverflow.com/questions/3906222/printing-osgi-bundle-classpath 这个Answer描述的是类似的问题。
目前对OSGI的底层原理和类加载器了解比较少,针对这个问题,采用的方法还是覆盖jar包中的类,将xml文件放在指定位置,不扫描jar,去指定位置读取。
4. bundle的文件读取问题
将xml文件放在src/resources文件夹下,采用的文件加载方式为:
URL url = this.getClass().getClassLoader().getResource(directory);
运行karaf之后,获取到的url为 bundleresource://214.fwk1205445235/converclass/,并不是常规的file:// 开头的协议,因此还是会报找不到文件错误。网络上的一种解决方法为https://blog.csdn.net/windrui/article/details/40581219
5. xml文件解析异常
javax.xml.parsers.FactoryConfigurationError: Provider com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl could not be instantiated: java.lang.ClassCastException: com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl cannot be cast to javax.xml.parsers.SAXParserFactory
相似问题记录:
https://stackoverflow.com/questions/2619880/unbelievable-cannot-cast-from-class-x-to-its-super-class
http://www.voidcn.com/article/p-annolfiy-btt.html