背景
系统提供为外部应用程序提供了一个验证flink sql语法以及在线试运行flink sql的接口。
bug
在pom.xml引入cdc依赖:
<dependency>
<groupId>com.ververica</groupId>
<artifactId>flink-sql-connector-oracle-cdc</artifactId>
<version>${flink.cdc.version}</version>
</dependency>
使用idea启动springboot应用,控制台输入如下:
可以看到没有任务的异常日志,只有 Process finished with exit code 1。
排查
修改Application 启动类增加异常打印:
@Configuration
@RefreshScope
@EnableDiscoveryClient
@EnableFeignClients
@EnableCaching
@EnableAsync
@SpringBootApplication
public class Application {
public static void main(String[] args) {
try {
SpringApplication.run(Application.class, args);
} catch (Exception e) {
e.printStackTrace(System.err);
throw new RuntimeException(e);
}
}
}
再次运行,提示 javax.xml.parsers.ParserconfiqurationException create breakpoint : SAx feature 'http://xm.org/sax/features/external-general-entities'not supported
从错误日志可以看出来,cdc依赖包中的oracle.xml.jaxp.JXSAXParserFactory与logback存在冲突导致致 logback 初始化报错,异常位置在 ch.qos.logback.core.joran.event.SaxEventRecorder#buildSaxParser,SAXParserFactory spf = SAXParserFactory.newInstance();这一行获取到的 SAXParserFactory 实例是cdc包中的错误实现
SAXParserFactory 作为 XML 文档解析器的接口,核心入口为 javax.xml.parsers.FactoryFinder#find,初始化该类实例的逻辑如下:
- 检验系统属性 javax.xml.parsers.SAXParserFactory是否设置,如果有使用该值
- 读取 ${java.home}/conf/jaxp.properties 配置 javax.xml.parsers.SAXParserFactory
- 依据 java.util.ServiceLoader 查找实现了 SAXParserFactory 的类后,取第一个
三种方式未能找到,使用默认实现com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl。
解决
设置系统属性 javax.xml.parsers.SAXParserFactory,启动正常
@Configuration
@RefreshScope
@EnableDiscoveryClient
@EnableFeignClients
@EnableCaching
@EnableAsync
@SpringBootApplication
public class Application {
public static void main(String[] args) {
try {
// FIX javax.xml.parsers.ParserConfigurationException: SAX feature 'http://xml.org/sax/features/external-general-entities' not supported.
System.setProperty("javax.xml.parsers.SAXParserFactory", "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
SpringApplication.run(Application.class, args);
} catch (Exception e) {
e.printStackTrace(System.err);
throw new RuntimeException(e);
}
}
}