问题现象
java 调用Kettle时候,提示
错误从XML文件读取转换
Unable to load step info from XML step nodejava.util.ConcurrentModificationException
at java.lang.Thread.run (Thread.java:748)
at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:617)
at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1142)
at java.util.concurrent.FutureTask.run (FutureTask.java:266)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0 (AsyncExecutionInterceptor.java:115)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint (CglibAopProxy.java:749)
at org.springframework.cglib.proxy.MethodProxy.invoke (MethodProxy.java:218)
at com.transino.EtlService.EtlDoSubTask$$FastClassBySpringCGLIB$$bc13f8b4.invoke (<generated>:-1)
at com.transino.EtlService.EtlDoSubTask.enterSubTask (EtlDoSubTask.java:89)
at com.transino.EtlService.EtlDoSubTask.doSubTask (EtlDoSubTask.java:154)
at com.transino.EtlService.EtlDoSubTask.executeSubTask (EtlDoSubTask.java:361)
at com.transino.EtlService.EtlDoSubTask.dataFileMonitoringDownload (EtlDoSubTask.java:319)
at com.transino.UtileFile.KettleTool.runTransfer (KettleTool.java:53)
at org.pentaho.di.trans.TransMeta.<init> (TransMeta.java:2690)
at org.pentaho.di.trans.TransMeta.<init> (TransMeta.java:2718)
at org.pentaho.di.trans.TransMeta.<init> (TransMeta.java:2744)
at org.pentaho.di.trans.TransMeta.<init> (TransMeta.java:2759)
at org.pentaho.di.trans.TransMeta.<init> (TransMeta.java:2774)
at org.pentaho.di.trans.TransMeta.<init> (TransMeta.java:2813)
at org.pentaho.di.trans.TransMeta.loadXML (TransMeta.java:3028)
at org.pentaho.di.trans.step.StepMeta.<init> (StepMeta.java:280)
at org.pentaho.di.core.plugins.PluginRegistry.findPluginWithId (PluginRegistry.java:677)
at org.pentaho.di.core.plugins.PluginRegistry.getPlugins (PluginRegistry.java:230)
at java.util.ArrayList$Itr.next (ArrayList.java:851)
at java.util.ArrayList$Itr.checkForComodification (ArrayList.java:901)
模拟复现
首先,你要保证kettle文件没有问题,本机上可以运行,只是java调用有问题。
本项目是多线程产品,多线程调用kettle,传递了kettle文件路径和kettle参数,然后多线程调用时候,偶尔会出现次问题,出现概率随机,DEBUG也无法进行复现。
大多数是:第一次项目启动运行,没有问题,第二次关闭项目再启动,kettle执行一半时候,强行关闭项目,第三次项目启动,复发概率在80%以上。
猜想原因:
1.可能资源没有释放,由于java 调用的是kettleApi,调用一半资源没有释放,导致这个问题。
2.多线程调用初始化代码时线称冲突,由于我们的多线程是并发执行,看执行时间是在同一秒执行的,怀疑代码对多线程有冲突。
解决方案(临时解决方案)
1.使用线称休眠策略解决;
long i=new Random().nextInt(5000-1000+1)+1000; //随机1000-5000之间的数值,也就是每个线称延迟1-5秒钟
Thread.sleep(i);
本策略主要考虑两点:资源释放和代码冲突,通过随机数来控制多线程同时调用kettle中间间隔时差,本次控制在5秒内,是可以接收的范围内,经过多次测试,解决了代码异常的问题。
2.使用try catch 异常捕获
经过测试发现,该异常并不会导致kettle不执行,kettle依旧执行,但是会返回一个错误信息,而kettle中的数据执行没有因此打断,数据也正常加载和处理,所以采用拦截Unable to load step info from XML step nodejava.util.ConcurrentModificationException异常,进行屏蔽即可。
try{
//异常信息
}catch (Exception ex){
//捕获异常即可
}
最后
这是我总结的经验,如果大家有更好的,希望能进行下方留言,谢谢