Tomcat9 抱怨找不到 javax.sql.DataSource 类的类
Posted
技术标签:
【中文标题】Tomcat9 抱怨找不到 javax.sql.DataSource 类的类【英文标题】:Tomcat9 complaining on class not found for javax.sql.DataSource class 【发布时间】:2020-11-12 02:35:08 【问题描述】:Tomcat9 在基于 Linux 的 VM 上运行,当 Jdk11 编译的 war 文件部署在 tomcat 中时,启动时出现以下错误。在启动 tomcat 时发生以下错误。如何解决此类未找到异常。是否要显式添加特定模块 java.sql?
Jul 22, 2020 1:49:45 AM org.apache.catalina.startup.Catalina start
SEVERE: The required Server component failed to start so Tomcat is unable to start.
org.apache.catalina.LifecycleException: Failed to start component [StandardServer[43004]]
at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:343)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:474)
Caused by: java.lang.NoClassDefFoundError: javax/sql/DataSource
at java.base/java.lang.ClassLoader.findBootstrapClass(Native Method)
at java.base/java.lang.ClassLoader.findBootstrapClassOrNull(ClassLoader.java:1258)
at java.base/java.lang.System$2.findBootstrapClassOrNull(System.java:2131)
at java.base/jdk.internal.loader.ClassLoaders$BootClassLoader.loadClassOrNull(ClassLoaders.java:118)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:616)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:640)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:616)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:576)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
我尝试在 tomcat 启动脚本中添加“--add-modules java.sql”。但仍然没有区别。还有一件奇怪的事情是,当添加 '-verbose:module' 选项时,它清楚地表明模块 java.sql 已加载,但仍以 NoClassDefFoundError: javax/sql/DataSource 结束。
find /usr/lib/jvm/adoptopenjdk-11-hotspot -name java.sql.jmod -exec jar tf '' \; | grep DataSource
classes/javax/sql/XADataSource.class
classes/javax/sql/ConnectionPoolDataSource.class
classes/javax/sql/DataSource.class
classes/javax/sql/CommonDataSource.class
java 版本:
$ java -version
openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.7+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.7+10, mixed mode)
我们在 server.xml 中有以下块
<Resource
name="jdbc/ILOraclePool"
auth="Container"
factory="com.xyz.tomcat.ucp.UcpDataSourceFactory" (this class extends oracle.ucp.jdbc.PoolDataSourceImpl)
type="oracle.ucp.jdbc.PoolDataSource"
description="main DB"
connectionFactoryClassName="oracle.jdbc.pool.OracleDataSource"
....
/>
【问题讨论】:
我了解 server.xml 文件中的我认为 tomcat 正在使用其他一些 JVM。检查一下。
打开tomcat9/bin
目录中的catalina.sh并导出JAVA_HOME。
export JAVA_HOME=/usr/lib/jvm/adoptopenjdk-11-hotspot
【讨论】:
@24_Jogi 这个有用吗 有趣的是,如果我从 server.xml 中删除对于应用服务器中的托管资源,最好将相关的库(例如JDBC驱动程序)复制到应用服务器特定的libs文件夹(例如Tomcat的catalina/lib, Glassfish 的 domain/yourdomain/lib 等)并将其注册为主机/域范围或在服务器配置文件中全局注册。
据我所知,一些 JDBC 驱动程序在打包到部署到 Tomcat 的可部署战争中时不起作用。并且在使用 Glassfish、Wildfly 等时,我总是使用服务器工具(UI、CLI、Maven 插件等)在服务器配置中注册 JDBC/Datasource 相关资源。
更新:我创建了一个新的 repo 来演示 Spring Boot 中的这种用法,请查看 here。
oracle-jndi-ds-jar 作为 Spring Boot jar 运行。 oracle-jndi-ds-war 在外部 Apache Tomcat 中作为战争运行。两者都包括对 Java 11、Oracle XE 18.4.0、JNDI 数据源的 IT 测试。
mvn verify -Pit
【讨论】:
是的,没错。我已经在 tomcat lib 中有 oracle 驱动程序 jar(ucp.jar、ojdbc8.jar、ons.jar、oraclepki.jar、simplefan.jar、aspectjweaver.jar) @24_Jogi 还是没有运气?就我个人而言,这些年来我没有使用过 oracle 和独立的 tomcat。但是我昨天自己验证了这个组合(oracle 18+java 11+tomcat 9),一切都按预期工作。我很快就会分享我的样品。【参考方案3】:首先确保 $CATALINA_HOME/lib
中存在来自同一版本(例如版本 12.2)的 Oracle JDBC jar ojdbc8.jar
、ucp.jar
和 ons.jar
。确保所有三个 jar 文件都来自相同的数据库版本。不要混合这些罐子的版本。请始终尝试使用最新的 JDBC 驱动程序和 UCP,以利用最新的功能和性能改进。
另外,我建议您将工厂类更改为oracle.ucp.jdbc.PoolDataSourceImpl
。
希望这应该可以解决问题。如果没有帮助,请将 JNDI 查找代码和 DataSource 配置发布到web.xml
。
【讨论】:
我已验证 oracle 驱动程序 jar 来自相同版本 12.2.0.1 和最新的 ojdbc8 [oracle.com/database/technologies/jdbc-ucp-122-downloads.html] 可用。关于替换工厂类,我们有一个自定义类,它扩展了相同的 PoolDataSourceImpl 只是覆盖了 getObjectInstance 方法以满足我们的自定义需求,它在 Tomcat8+Jdk8 上运行良好。实际上我确实尝试过,用 PoolDataSourceImpl 替换,但仍然是同样的问题,NoClassDefFoundError : javax/sql/DataSource.【参考方案4】:您是否尝试过将其移至 context.xml ?查看Tomcat_Servlet 代码示例。
【讨论】:
以上是关于Tomcat9 抱怨找不到 javax.sql.DataSource 类的类的主要内容,如果未能解决你的问题,请参考以下文章