本文介绍了SpringBoot JNDI 数据源抛出 java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

之前也有人问过类似的问题,我已经解决了所有这些问题,但无法解决问题.相关问题 - Q1,Q2Q3Q4Q5Q6

Similar questions have been asked before and I went through all of those but not able to solve problem. Related Questions - Q1,Q2,Q3, Q4, Q5, Q6

我有一个带有 Spring Boot 的 Spring Batch 项目并尝试使用数据库连接池.我正在使用版本为 8.5.x 的嵌入式 tomcat 容器.

I have a Spring Batch project with Spring Boot and trying to use DB connection pools. I am using embedded tomcat container with version 8.5.x.

如果我使用 application.properties 指定数据源和池设置,一切正常.

Everything works fine if I use application.properties to specify data source and pool settings.

但是当我尝试使用 JNDI 时,出现异常 -

But when I try to use JNDI, I get exception -

Caused by: java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory

我在 Maven jars 中没有看到任何 jar 名称 tomcat-dbcp-** 所以我不确定是否需要包含任何新的依赖项或需要设置默认数据源工厂以及如何去做吧.

I don't see any jar names tomcat-dbcp-** in Maven jars so I am not sure if I need to include any new dependency or need to set default data source factory and how to go about it.

下面是我的 JNDI bean 设置,问题.我已经清除了某些值.

Below is my JNDI beans set up, Question. I have blanked out certain values.

@Bean
    public TomcatEmbeddedServletContainerFactory embeddedServletContainerFactory(){
        return new TomcatEmbeddedServletContainerFactory() {

            @Override
            protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
                    Tomcat tomcat) {
                tomcat.enableNaming();
                return super.getTomcatEmbeddedServletContainer(tomcat);
            }

            @Override
            protected void postProcessContext(Context context) {
                ContextResource resource = new ContextResource();
                resource.setName("jdbc/myDataSource");
                resource.setType(DataSource.class.getName());
                resource.setProperty("driverClassName", "com.ibm.db2.jcc.DB2Driver");
                resource.setProperty("url", "url");
                resource.setProperty("username", "user");
                resource.setProperty("password", "*****");
                context.getNamingResources().addResource(resource);
            }
        };
    }

    @Lazy
    @Bean(destroyMethod="")
    public DataSource jndiDataSource() throws IllegalArgumentException, NamingException {
        JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
        bean.setJndiName("java:comp/env/jdbc/myDataSource");
        bean.setProxyInterface(DataSource.class);
        bean.setLookupOnStartup(false);
        bean.afterPropertiesSet();
        return (DataSource)bean.getObject();
    }

我的 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <packaging>war</packaging>

    <groupId>***</groupId>
    <artifactId>***</artifactId>
    <version>1.0.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.0.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j</artifactId>
            <version>1.2.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>db2</groupId>
            <artifactId>db2jcc</artifactId>
            <version>4.0</version>
        </dependency>

        <dependency>
            <groupId>db2</groupId>
            <artifactId>db2jcc_license_cu</artifactId>
            <version>4.0</version>
        </dependency>
    </dependencies>

    <build>

        <plugins>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>1.4.0.RELEASE</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                <source>1.7</source>
                <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

推荐答案

我通过在我的 Resource 定义中设置 factory 属性解决了这个问题.resource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");

I solved the problem by setting factory attribute in my Resource Definition. resource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");

@Bean
public TomcatEmbeddedServletContainerFactory embeddedServletContainerFactory(){
    return new TomcatEmbeddedServletContainerFactory() {

        @Override
        protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
                Tomcat tomcat) {
            tomcat.enableNaming();
            return super.getTomcatEmbeddedServletContainer(tomcat);
        }

        @Override
        protected void postProcessContext(Context context) {
            ContextResource resource = new ContextResource();
            resource.setName("jdbc/myDataSource");
            resource.setType(DataSource.class.getName());
            resource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
            resource.setProperty("driverClassName", "com.ibm.db2.jcc.DB2Driver");
            resource.setProperty("url", "url");
            resource.setProperty("username", "user");
            resource.setProperty("password", "*****");
            context.getNamingResources().addResource(resource);
        }
    };
}

根据 tomcat 8 文档,它应该通过查看 DataSource 类型自动推断数据库池工厂类型,并且以某种方式默认为 DBCP 工厂,并且该类不在我的类路径中.

As per tomcat 8 documentation, it is supposed to automatically infer db pool factory type by looking at DataSource type and somehow it defaults to DBCP factory and that class is not there in my class path.

我想问题可以通过使 tomcat-dbcp-** jars 可用来解决,但我不确定如何使用 spring boot 或者即使使用 spring boot 可以做到这一点.

I guess so issue can be solved by making tomcat-dbcp-** jars available but I am not sure how to do that with spring boot or even if that is possible with spring boot.

我觉得奇怪的是 Spring Boot 不包括 tomcat-dbcp 依赖项作为 starter POM 的一部分,而是使用 DBCP 数据源工厂作为默认工厂.

What I find weird is Spring Boot not including tomcat-dbcp dependencies as part of starter POM but using DBCP DataSource factory as default factory.

这篇关于SpringBoot JNDI 数据源抛出 java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-09 11:51