背景:
业务场景:MySQL数据库定期从Oracle数据库中同步少量数据,几分钟一次
版本信息:服务器jdk1.8.0_171,开发编译环境jdk1.8.0_181 idea2023.1.2
技术框架:用了maven管理依赖,未发现spring等框架痕迹
问题描述
将代码少量改动后,本地编译外加依赖打成jar包。
部署到远程服务器时,运行出错,系统中查看报错信息:
出错原因:
java.lang.reflect.InvocationTargetException
原因分析:
差不多的代码,原有jar包在别的服务器可运行,说明是环境问题,搜索发现
原因:
1、包冲突、有重复包或者缺少包
2、项目jdk和部署jdk版本不一样,导致InvocationTargetException异常信息返回一个空值,没有调用invoc里的重写消息方法。
3、映射文件发生改变
方案:
1、包:直接自己挨着查看就是了,但是一定要注意遇到重复包的时候你的系统究竟需要哪一个版本
2、jdk版本:
⑴、更换jdk包
⑵、用一个方法统一处理该异常
3、映射文件发生改变
在项目中有的地方是使用反射机制进行的操作,可能对于类进行了某些更改,科室映射文件没有更改,采用匿名就会出现这样的问题,解决办法要么更改映射文件,要不不要使用匿名调用。
原文链接
由此推测是jdk版本不一致的原因,尝试将开发环境与生产环境用同版本jdk
解决方案:
方案一:更换jdk重新打包再部署(未实验,方案二可行则本方案理论上也可行)
方案二:更换jdk后重新编译,把改动代码的编译后的class文件放入原有可运行jar包(注意修改IP端口账号密码等配置)
- 加装jdk
从项目文件中找到171版本jdk进行安装,原有jdk无须理会,环境变量也不用修改 ctrl
+alt
+shift
+s
打开项目配置
project》sdk》add sdk 添加刚刚安装的jdk- 点击project下方的module选项卡
切换各个模块的sdk - 点击platforms and settings
选中原有的jdk,点击上方减号,从项目中去掉
新添加的jdk保留不动,点击apply应用,然后确定 - maven插件重新打包,发送到服务器
- 用压缩软件打开新包,把修改过的class文件覆盖到旧包中保存
- 运行成功
重逢再回首之2023年8月3日
背景
业务场景:依旧是同步任务,定期夸库同步少量数据,这次完全是在开发环境中
版本信息:jdk1.8.0_171 idea2023.1.2 MySQL5.6
技术框架:springboot上的若依系统二开
数据库是三库结构,一个源数据库Oracle,一个中间库MySQL,一个业务库MySQL
问题出现之前,将master和第三数据源做过对换,系统能运行,但是当时没有调测任务能不能成功运行
问题描述
新写了一个同步任务,之前用的jdk1.8.0_171,能成功运行,这次突然不行了
报错信息:
09:32:24.902 [http-nio-6666-exec-13] DEBUG c.r.q.m.S.selectJobById - [debug,137] - ==> Preparing: select job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark from sys_job where job_id = ?
09:32:24.903 [http-nio-6666-exec-13] DEBUG c.r.q.m.S.selectJobById - [debug,137] - ==> Parameters: 100(Long)
09:32:24.907 [http-nio-6666-exec-13] DEBUG c.r.q.m.S.selectJobById - [debug,137] - <== Total: 1
用药分类字典===视图同步到业务库===开始
09:32:24.909 [quartzScheduler_Worker-2] ERROR c.r.q.u.AbstractQuartzJob - [execute,49] - 任务执行异常 - :
java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.ruoyi.quartz.util.JobInvokeUtil.invokeMethod(JobInvokeUtil.java:61)
at com.ruoyi.quartz.util.JobInvokeUtil.invokeMethod(JobInvokeUtil.java:38)
at com.ruoyi.quartz.util.QuartzDisallowConcurrentExecution.doExecute(QuartzDisallowConcurrentExecution.java:19)
at com.ruoyi.quartz.util.AbstractQuartzJob.execute(AbstractQuartzJob.java:43)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: java.lang.NullPointerException: null
at com.ruoyi.quartz.task.syncTask.drugTypeHisToLight(syncTask.java:63)
... 10 common frames omitted
09:32:24.915 [quartzScheduler_Worker-2] DEBUG c.r.q.m.S.insertJobLog - [debug,137] - ==> Preparing: insert into sys_job_log( job_name, job_group, invoke_target, job_message, status, exception_info, create_time )values( ?, ?, ?, ?, ?, ?, sysdate() )
09:32:24.915 [quartzScheduler_Worker-2] DEBUG c.r.q.m.S.insertJobLog - [debug,137] - ==> Parameters: 用药分类字典视图同步到业务库(String), DEFAULT(String), com.ruoyi.quartz.task.syncTask.drugTypeHisToLight(String), 用药分类字典视图同步到业务库 总共耗时:1毫秒(String), 1(String), java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.ruoyi.quartz.util.JobInvokeUtil.invokeMethod(JobInvokeUtil.java:61)
at com.ruoyi.quartz.util.JobInvokeUtil.invokeMethod(JobInvokeUtil.java:38)
at com.ruoyi.quartz.util.QuartzDisallowConcurrentExecution.doExecute(QuartzDisallowConcurrentExecution.java:19)
at com.ruoyi.quartz.util.AbstractQuartzJob.execute(AbstractQuartzJob.java:43)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: java.lang.NullPointerException
at com.ruoyi.quartz.task.syncTask.drugTypeHisToLight(syncTask.java:63)
... 10 more
(String)
09:32:24.927 [quartzScheduler_Worker-2] DEBUG c.r.q.m.S.insertJobLog - [debug,137] - <== Updates: 1
09:32:24.938 [schedule-pool-2] DEBUG c.r.s.m.S.insertOperlog - [debug,137] - ==> Preparing: insert into sys_oper_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, cost_time, oper_time) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, sysdate())
09:32:24.939 [schedule-pool-2] DEBUG c.r.s.m.S.insertOperlog - [debug,137] - ==> Parameters: 定时任务(String), 2(Integer), com.ruoyi.quartz.controller.SysJobController.run()(String), PUT(String), 1(Integer), admin(String), null, /monitor/job/run(String), 127.0.0.1(String), 内网IP(String), {"jobGroup":"DEFAULT","jobId":100,"misfirePolicy":"0","params":{}}(String), {"msg":"操作成功","code":200}(String), 0(Integer), null, 16(Long)
09:32:24.970 [schedule-pool-2] DEBUG c.r.s.m.S.insertOperlog - [debug,137] - <== Updates: 1
原因分析
推测还是老问题,jdk版本,重新改一下jdk到181,这次我学聪明了,只添加181,不删除171,因为这里搞得jdk会影响其他项目(奇怪,明明只是项目配置,按理说相互之间不能影响的)
当然,没有解决这个问题,就算是只保留一个181jdk也不行了,果然和预感一样,没这么简单。
再次观察控制台错误日志,发现同步任务可以执行,但是service方法里的第一个断点都没进(我用debug模式启动的),看来是框架service这边的问题,Java基础框架原理真的重要啊!
突然回想起来,有个mapper好像没加mapper注解,倒是很像这个问题,但是加了也不行,根本就没运行到这里。
但是啊,但是,这里还有个空指针异常,看来根本就没装配上这个service。
stackoverflow上有同时出现这两个异常的问题,但他是因为把自动注入的变量写成了静态的所以才出的问题,启发给我的点就是检查一下调用的service方法是否在接口中有定义,但是这个很明显不是,因为接口没有的话我就没法调用了。
在帖子里的评论有一个链接,讲了一些关于注解的东西,看了一点,有空再来看看
直觉告诉我,一定是哪里没有用框架组件(component、service、mapper等),或者是哪里没有用注解声明组件,但是之前检查出来了mapper注解漏了一个,别的就没再有了,查看定时任务类的上方,也是有注解的:
@Component("syncTask")
解决方案
既然定时任务这里注册组件了,那系统的定时任务配置,是不是应该也用组件来调用呢?
再次回到系统中,果然发现:
果然,是我写的调用目标写的不对,上边的都短我竟然没发现。
修改调用目标,写上从组件开始调用的任务,问题消失
插曲
因为项目的主要功能是同步,数据有点bug,本来应该是唯一的,源数据中有重复数据,这只能怪自己考虑不周。 在数据重复时,利用j8stream语法转换list为map时会报错:
16:44:02.853 [http-nio-6666-exec-1] INFO o.a.c.c.C.[.[.[/] - [log,173] - Initializing Spring DispatcherServlet 'dispatcherServlet'
16:44:03.279 [http-nio-6666-exec-1] DEBUG c.r.q.m.S.selectJobById - [debug,137] - ==> Preparing: select job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark from sys_job where job_id = ?
16:44:03.281 [http-nio-6666-exec-1] DEBUG c.r.q.m.S.selectJobById - [debug,137] - ==> Parameters: 100(Long)
16:44:03.285 [http-nio-6666-exec-1] DEBUG c.r.q.m.S.selectJobById - [debug,137] - <== Total: 1
用药分类字典===视图同步到业务库===开始
16:44:03.306 [quartzScheduler_Worker-1] INFO c.r.f.d.DynamicDataSourceContextHolder - [setDataSourceType,26] - 切换到MASTER数据源
16:44:03.311 [quartzScheduler_Worker-1] INFO c.r.f.d.DynamicDataSourceContextHolder - [setDataSourceType,26] - 切换到SLAVE数据源
16:44:03.325 [schedule-pool-1] DEBUG c.r.s.m.S.insertOperlog - [debug,137] - ==> Preparing: insert into sys_oper_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, cost_time, oper_time) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, sysdate())
16:44:03.337 [schedule-pool-1] DEBUG c.r.s.m.S.insertOperlog - [debug,137] - ==> Parameters: 定时任务(String), 2(Integer), com.ruoyi.quartz.controller.SysJobController.run()(String), PUT(String), 1(Integer), admin(String), null, /monitor/job/run(String), 127.0.0.1(String), 内网IP(String), {"jobGroup":"DEFAULT","jobId":100,"misfirePolicy":"0","params":{}}(String), {"msg":"操作成功","code":200}(String), 0(Integer), null, 47(Long)
16:44:03.343 [schedule-pool-1] DEBUG c.r.s.m.S.insertOperlog - [debug,137] - <== Updates: 1
16:44:03.996 [quartzScheduler_Worker-1] INFO c.a.d.p.DruidDataSource - [init,996] - {dataSource-2} inited
16:44:03.996 [quartzScheduler_Worker-1] DEBUG c.r.t.m.V.selectVDrugTypeList - [debug,137] - ==> Preparing: select DRUG_TYPE_CODE, DRUG_TYPE_NAME from V_SW_DRUG_TYPE
16:44:04.024 [quartzScheduler_Worker-1] DEBUG c.r.t.m.V.selectVDrugTypeList - [debug,137] - ==> Parameters:
16:44:04.199 [quartzScheduler_Worker-1] DEBUG c.r.t.m.V.selectVDrugTypeList - [debug,137] - <== Total: 500
16:44:04.200 [quartzScheduler_Worker-1] INFO c.r.f.d.DynamicDataSourceContextHolder - [setDataSourceType,26] - 切换到MASTER数据源
16:44:04.201 [quartzScheduler_Worker-1] DEBUG c.r.s.m.S.selectDictDataList - [debug,137] - ==> Preparing: select dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark from sys_dict_data WHERE dict_type = ? order by dict_sort asc
16:44:04.201 [quartzScheduler_Worker-1] DEBUG c.r.s.m.S.selectDictDataList - [debug,137] - ==> Parameters: drug_type(String)
16:44:04.227 [quartzScheduler_Worker-1] DEBUG c.r.s.m.S.selectDictDataList - [debug,137] - <== Total: 501
16:44:04.234 [quartzScheduler_Worker-1] ERROR c.r.q.u.AbstractQuartzJob - [execute,49] - 任务执行异常 - :
java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.ruoyi.quartz.util.JobInvokeUtil.invokeMethod(JobInvokeUtil.java:61)
at com.ruoyi.quartz.util.JobInvokeUtil.invokeMethod(JobInvokeUtil.java:33)
at com.ruoyi.quartz.util.QuartzDisallowConcurrentExecution.doExecute(QuartzDisallowConcurrentExecution.java:19)
at com.ruoyi.quartz.util.AbstractQuartzJob.execute(AbstractQuartzJob.java:43)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: java.lang.IllegalStateException: Duplicate key com.ruoyi.common.core.domain.entity.SysDictData@1e597602[
dictCode=1575
dictSort=0
dictLabel=曲克芦丁片
dictValue=15070042666666
dictType=drug_type
cssClass=<null>
listClass=default
isDefault=N
status=1
createBy=
createTime=Thu Aug 03 16:24:04 CST 2023
updateBy=<null>
updateTime=<null>
remark=<null>
]
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1254)
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.ruoyi.system.service.impl.SysDictDataServiceImpl.compareDictData(SysDictDataServiceImpl.java:193)
at com.ruoyi.system.service.impl.SysDictDataServiceImpl.getHisDrugType(SysDictDataServiceImpl.java:156)
at com.ruoyi.system.service.impl.SysDictDataServiceImpl$$FastClassBySpringCGLIB$$88d3e8dd.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
at com.ruoyi.framework.aspectj.DataSourceAspect.around(DataSourceAspect.java:49)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at com.ruoyi.system.service.impl.SysDictDataServiceImpl$$EnhancerBySpringCGLIB$$4ab8d42f.getHisDrugType(<generated>)
at com.ruoyi.quartz.task.syncTask.drugTypeHisToLight(syncTask.java:63)
... 10 common frames omitted
16:44:04.237 [quartzScheduler_Worker-1] DEBUG c.r.q.m.S.insertJobLog - [debug,137] - ==> Preparing: insert into sys_job_log( job_name, job_group, invoke_target, job_message, status, exception_info, create_time )values( ?, ?, ?, ?, ?, ?, sysdate() )
16:44:04.238 [quartzScheduler_Worker-1] DEBUG c.r.q.m.S.insertJobLog - [debug,137] - ==> Parameters: 用药分类字典视图同步到业务库(String), DEFAULT(String), syncTask.drugTypeHisToLight(String), 用药分类字典视图同步到业务库 总共耗时:931毫秒(String), 1(String), java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.ruoyi.quartz.util.JobInvokeUtil.invokeMethod(JobInvokeUtil.java:61)
at com.ruoyi.quartz.util.JobInvokeUtil.invokeMethod(JobInvokeUtil.java:33)
at com.ruoyi.quartz.util.QuartzDisallowConcurrentExecution.doExecute(QuartzDisallowConcurrentExecution.java:19)
at com.ruoyi.quartz.util.AbstractQuartzJob.execute(AbstractQuartzJob.java:43)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: java.lang.IllegalStateException: Duplicate key com.ruoyi.common.core.domain.entity.SysDictData@1e597602[
dictCode=1575
dictSort=0
dictLabel=曲克芦丁片
dictValue=15070042666666
dictType=drug_type
cssClass=<null>
listClass=default
isDefault=N
status=1
createBy=
createTime=Thu Aug 03 16:24:04 CST 2023
updateBy=<null>
updateTime=<null>
remark=<null>
]
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1254)
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.ruoyi.system.service.i(String)
16:44:04.249 [quartzScheduler_Worker-1] DEBUG c.r.q.m.S.insertJobLog - [debug,137] - <== Updates: 1
注意,这里面同样包含本文主题中的错误,但是原因里面也有提到,那就是Duplicate key,这算是另一种原因,对重复数据做好逻辑处理,去重就好了。