解决datart空指针问题 ERROR datart.server.config.WebExceptionHandler : null java.lang.NullPointerException: null
1、问题描述
datart版本:为datart最后一个发布版本1.0.0-rc.3 Release
在使用datart 对接clickhouse的过程中,不能够同步clickhouse的元数据,但是可以查看clickhouse表数据。这就需要你时刻记得你clickhouse有哪些表。这就很鸡肋。
如果clickhouse元数据同步不过来,右侧数据源信息处是空的。以下图片是同步成功后的照片。
查看运行日志,发现有空指针报错。
2024-08-27 14:31:01.218 [http-nio-0.0.0.0-8080-exec-3] INFO d.data.provider.jdbc.DataSourceFactoryDruidImpl : druid data source created (DataSource-887852319)
2024-08-27 14:31:01.218 [http-nio-0.0.0.0-8080-exec-3] ERROR com.alibaba.druid.pool.DruidDataSource : testWhileIdle is true, validationQuery not set
2024-08-27 14:31:01.219 [http-nio-0.0.0.0-8080-exec-3] INFO com.alibaba.druid.pool.DruidDataSource : {dataSource-2} inited
2024-08-27 14:31:10.888 [http-nio-0.0.0.0-8080-exec-3] INFO d.d.provider.jdbc.adapters.JdbcDataProviderAdapter : Database 'catalogs' is empty, get databases with 'schemas'
2024-08-27 14:31:10.960 [http-nio-0.0.0.0-8080-exec-3] ERROR datart.server.config.WebExceptionHandler : null
java.lang.NullPointerException: null
at datart.data.provider.jdbc.DataTypeUtils.jdbcType2DataType(DataTypeUtils.java:61)
at datart.data.provider.jdbc.adapters.JdbcDataProviderAdapter.readTableColumn(JdbcDataProviderAdapter.java:193)
at datart.data.provider.jdbc.adapters.JdbcDataProviderAdapter.readTableColumn(JdbcDataProviderAdapter.java:176)
at datart.data.provider.JdbcDataProvider.readTableColumns(JdbcDataProvider.java:85)
at datart.data.provider.ProviderManager.readTableColumns(ProviderManager.java:114)
at datart.server.service.impl.DataProviderServiceImpl.readTableColumns(DataProviderServiceImpl.java:140)
at datart.server.job.SchemaSyncJob.execute(SchemaSyncJob.java:94)
at datart.server.service.impl.SourceServiceImpl.syncSourceSchema(SourceServiceImpl.java:166)
at datart.server.service.impl.SourceServiceImpl$$FastClassBySpringCGLIB$$668e814e.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
at datart.server.service.impl.SourceServiceImpl$$EnhancerBySpringCGLIB$$96af554d.syncSourceSchema(<generated>)
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.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy183.syncSourceSchema(Unknown Source)
at datart.server.controller.SourceController.syncSourceSchemas(SourceController.java:117)
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.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
2、解决问题
分析报错日志,发现是由于空指针导致的报错,进而导致相关的元数据同步出现了问题。
这个我们就需要下载datart源代码,进行代码分析,看看为什么会有空指针,以及如何解决空指针。
从日志我们可以看到最终报空指针的类是datart.data.provider.jdbc.DataTypeUtils,对应的方法是jdbcType2DataType方法。日志中还显示了是具体的哪一行出现了空指针(第61行),其实就是下面的
family变量。我们只需对其增加一个判空的判断就可以解决了。
源代码链接
https://gitee.com/running-elephant/datart/
官方文档
https://running-elephant.github.io/datart-docs/docs/first-visualization.html
我这里是直接将family为空的就当做string进行返回。
然后重新打包
替换datart/lib下面的相同命名的jar包即可。空指针问题就解决了。(打包过程中有可能会显示少包,缺什么包就在pom文件内加,当然有些包已经在datart的其他项目中已经有过引用,可以直接复制过来使用)。
3、问题解决过程回溯
其实在这个过程中我还做了好多的代码测试,重写了clickhouse的ClickHouseDataProviderAdapter类
并编写了测试类看解析元数据是否有问题。