小编典典

使用MySQL进行JDBC连接池的Jetty时,JNDI查找失败?

java

我正在使用带有标准MySQL连接器API的Jetty 9.2(嵌入式),并且对应该如何设置它感到非常困惑。目前,我的 web.xml
文件中包含以下内容:

<webapp ...

    <resource-ref>
        <description>JDBC Data Source</description>
        <res-ref-name>jdbc/DataSource</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
</webapp>

…这在我的jetty-env.xml中:

<Configure class="org.eclipse.jetty.webapp.WebAppContext">

   <New id="DatabaseConnector" class="org.eclipse.jetty.plus.jndi.Resource">
        <Arg></Arg>
        <Arg>jdbc/DataSource</Arg>
        <Arg>
            <New class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
                <Set name="Url">jdbc:mysql://localhost:3306/DBName</Set>
                <Set name="User">user</Set>
                <Set name="Password">pass</Set>
            </New>
        </Arg>
    </New>

 </Configure>

…然后执行以下代码初始化:

Context envCtx = (Context) new InitialContext().lookup("java:comp/env");
DataSource datasource = (DataSource) envCtx.lookup("jdbc/DataSource");

当我尝试启动服务器时,出现错误javax.naming.NameNotFoundException; remaining name 'jdbc/DataSource'。我已经在代码初始化中尝试了许多不同的字符串变体,例如删除了lookupInitialContext对象的调用,但是我只是不断地获得相同错误的变体,只是name值不同。

这两个xml文件都位于我的/WAR/WEB-INF目录中。我查看了以前的问题和教程,博客等的大量内容,但是却一无所获。


阅读 337

收藏
2020-11-26

共1个答案

小编典典

这是嵌入式Jetty特有的问题的组合。

首先,在我实际启动Web服务器之前(即在调用之前),正在配置和启动Web服务器的启动器代码正在执行JNDI查找server.start(),因此在该阶段未初始化JNDI配置。

但是,即使进行此更改也不起作用,因为envCtx.lookup("jdbc/DataSource")需要从与WebApp关联的线程中进行调用。因此,我将该代码移到了静态块,该静态块在Web服务器请求首次请求数据库连接时被调用。

最后,我在 启动器代码中得到了以下内容

public static void main(String[] args) {
    Server server = new Server();

    //Enable parsing of jndi-related parts of web.xml and jetty-env.xml
    ClassList classlist = ClassList.setServerDefault(server);
    classlist.addAfter(
            "org.eclipse.jetty.webapp.FragmentConfiguration", 
            "org.eclipse.jetty.plus.webapp.EnvConfiguration", 
            "org.eclipse.jetty.plus.webapp.PlusConfiguration");
...
...
server.start();

无法通过该主线程进行JNDI查找,因此将其放置在类似于initservlet请求的方法的地方,或者像我一样,将其放置在servlet使用的静态数据库访问器类的同步方法中,例如

public class DatabaseUtils {

    private static DataSource datasource;

    private static synchronized Connection getDBConnection() throws SQLException {
        if (datasource == null) {
            initDataSource();
        }
        return datasource.getConnection();
    }

    public static void initDataSource() {
        try {
             datasource = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/DataSource");
             LOG.info("Database connection pool initalized successfully");
        } catch (Exception e) {
            LOG.error("Error while initialising the database connection pool", e);
        }
    }
2020-11-26