如何为 tomcat 6 及其部署的 webapps 正确配置 JNDI?

Posted

技术标签:

【中文标题】如何为 tomcat 6 及其部署的 webapps 正确配置 JNDI?【英文标题】:How to configure properly JNDI for tomcat 6 and its deployed webapps? 【发布时间】:2013-07-02 05:55:06 【问题描述】:

我有一个嵌入式 derby 数据库,其中包含用于 USERS、ROLES、USERS_ROLES 等的表。我的要求是使用它进行 tomcat 身份验证。另外,我创建了一个 spring webapp 以便以更简单的方式管理用户、角色等。

之前我在 applicationContext 中定义了这个数据源:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
    p:driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
    p:url="jdbc:derby:C:\tools\derbydb"
    p:connectionProperties=""
    p:username="APP"
    p:password="" />

我已将此方法更改为 JNDI,现在我已在 webapp/WEB-INF/context.xml 中定义了 db 资源

<Context>
    <Resource name="jdbc/adminDB" auth="Container" type="javax.sql.DataSource"
            maxActive="20" maxIdle="10" username="APP" password=""
            driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
            url="jdbc:derby:C:\tools\derbydb"/>
</Context>

在我的 applicationContext.xml 中:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/adminDB"/>
</bean>

在 Eclipse 中它工作正常。我可以读取值、编辑、登录等。

我的问题与在 tomcat 6 上允许这样做有关。我已经阅读了一些页面,包括 *** 的问题,但我没有找到我的具体问题。我已经部署了另一个应用程序,它使用 tomcat 安全性来访问一些数据。它是由第三方开发的应用程序。使用旧配置可以正常工作(server.xml):

<Realm className="org.apache.catalina.realm.JDBCRealm" driverName="org.apache.derby.jdbc.EmbeddedDriver" connectionURL="jdbc:derby:C:\tools\derbydb" connectionName="APP" connectionPassword="" userTable="USERS" userNameCol="USERNAME" userCredCol="PASSWORD" userRoleTable="V_USERS_ROLES" roleNameCol="ROLENAME"/>

并且我能够使用 tomcat 使用数据库中定义的用户登录。但是现在,我定义了这样的东西(server.xml):

<Realm className="org.apache.catalina.realm.DataSourceRealm" dataSourceName="jdbc/adminDB" userTable="USERS" userNameCol="USERNAME" userCredCol="PASSWORD" userRoleTable="V_USERS_ROLES" roleNameCol="ROLENAME"/>

并在 server.xml (GlobalNamingResources) 中

<Resource name="jdbc/adminDB" auth="Container" type="javax.sql.DataSource"
        maxActive="20" maxIdle="10" username="APP" password=""
        driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
        url="jdbc:derby:C:\tools\derbydb"/>

当我尝试登录时出现此错误:

SEVERE: Excepci¾n realizando autenticaci¾n
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Failed to s
tart database 'C:\tools\derbydb' with class loader org.apache.catalina.loader.StandardClassLoader@23
49e5ef, see the next exception for details.)
        at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createPoolableConnectionFactory(BasicDataSour
ce.java:1549)
        at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1388)
        at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
        at org.apache.catalina.realm.DataSourceRealm.open(DataSourceRealm.java:416)
        at org.apache.catalina.realm.DataSourceRealm.authenticate(DataSourceRealm.java:296)
        at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(BasicAuthenticator.java
:181)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:528)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.ja
va:606)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
        at java.lang.Thread.run(Thread.java:722)
Caused by: java.sql.SQLException: Failed to start database 'C:\tools\derbydb' with class loader org.
apache.catalina.loader.StandardClassLoader@2349e5ef, see the next exception for details.
        at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source)
        at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source)
        at org.apache.derby.impl.jdbc.Util.seeNextException(Unknown Source)
        at org.apache.derby.impl.jdbc.EmbedConnection.bootDatabase(Unknown Source)
        at org.apache.derby.impl.jdbc.EmbedConnection.<init>(Unknown Source)
        at org.apache.derby.impl.jdbc.EmbedConnection30.<init>(Unknown Source)
        at org.apache.derby.impl.jdbc.EmbedConnection40.<init>(Unknown Source)
        at org.apache.derby.jdbc.Driver40.getNewEmbedConnection(Unknown Source)
        at org.apache.derby.jdbc.InternalDriver.connect(Unknown Source)
        at org.apache.derby.jdbc.AutoloadedDriver.connect(Unknown Source)
        at org.apache.tomcat.dbcp.dbcp.DriverConnectionFactory.createConnection(DriverConnectionFact
ory.java:38)
        at org.apache.tomcat.dbcp.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactor
y.java:582)
        at org.apache.tomcat.dbcp.dbcp.BasicDataSource.validateConnectionFactory(BasicDataSource.jav
a:1556)
        at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createPoolableConnectionFactory(BasicDataSour
ce.java:1545)
        ... 14 more
Caused by: java.sql.SQLException: Failed to start database 'C:\tools\derbydb' with class loader org.
apache.catalina.loader.StandardClassLoader@2349e5ef, see the next exception for details.
        at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
        at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown S
ource)
        ... 28 more
Caused by: java.sql.SQLException: Another instance of Derby may have already booted the database C:\
tools\derbydb.
        at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
        at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown S
ource)
        at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source)
        at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
        ... 25 more
Caused by: ERROR XSDB6: Another instance of Derby may have already booted the database C:\tools\derb
ydb.
        at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
        at org.apache.derby.impl.store.raw.data.BaseDataFileFactory.privGetJBMSLockOnDB(Unknown Sour
ce)
        at org.apache.derby.impl.store.raw.data.BaseDataFileFactory.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.apache.derby.impl.store.raw.data.BaseDataFileFactory.getJBMSLockOnDB(Unknown Source)
        at org.apache.derby.impl.store.raw.data.BaseDataFileFactory.boot(Unknown Source)
        at org.apache.derby.impl.services.monitor.BaseMonitor.boot(Unknown Source)
        at org.apache.derby.impl.services.monitor.TopService.bootModule(Unknown Source)
        at org.apache.derby.impl.services.monitor.BaseMonitor.startModule(Unknown Source)
        at org.apache.derby.iapi.services.monitor.Monitor.bootServiceModule(Unknown Source)
        at org.apache.derby.impl.store.raw.RawStore.boot(Unknown Source)
        at org.apache.derby.impl.services.monitor.BaseMonitor.boot(Unknown Source)
        at org.apache.derby.impl.services.monitor.TopService.bootModule(Unknown Source)
        at org.apache.derby.impl.services.monitor.BaseMonitor.startModule(Unknown Source)
        at org.apache.derby.iapi.services.monitor.Monitor.bootServiceModule(Unknown Source)
        at org.apache.derby.impl.store.access.RAMAccessManager.boot(Unknown Source)
        at org.apache.derby.impl.services.monitor.BaseMonitor.boot(Unknown Source)
        at org.apache.derby.impl.services.monitor.TopService.bootModule(Unknown Source)
        at org.apache.derby.impl.services.monitor.BaseMonitor.startModule(Unknown Source)
        at org.apache.derby.iapi.services.monitor.Monitor.bootServiceModule(Unknown Source)
        at org.apache.derby.impl.db.BasicDatabase.bootStore(Unknown Source)
        at org.apache.derby.impl.db.BasicDatabase.boot(Unknown Source)
        at org.apache.derby.impl.services.monitor.BaseMonitor.boot(Unknown Source)
        at org.apache.derby.impl.services.monitor.TopService.bootModule(Unknown Source)
        at org.apache.derby.impl.services.monitor.BaseMonitor.bootService(Unknown Source)
        at org.apache.derby.impl.services.monitor.BaseMonitor.startProviderService(Unknown Source)
        at org.apache.derby.impl.services.monitor.BaseMonitor.findProviderAndStartService(Unknown So
urce)
        at org.apache.derby.impl.services.monitor.BaseMonitor.startPersistentService(Unknown Source)

        at org.apache.derby.iapi.services.monitor.Monitor.startPersistentService(Unknown Source)
        ... 25 more

似乎另一个 JVM 的应用程序锁定了 derby db。但是除了tomcat本身之外,我没有任何东西可以访问数据库。而且我目前还没有部署管理 web 应用程序。我只部署了使用 tomcat 登录的应用程序。有人知道发生了什么吗?

顺便说一句...为了从管理员 webapp 访问数据库,此解决方案是否正确?还是需要在 context.xml 中定义资源?

任何有帮助的答案都会被投票

谢谢

【问题讨论】:

【参考方案1】:

单个 Tomcat 应用程序服务器中的每个单独的应用程序都被视为一个单独的 Derby 实例。

所以同一个 Tomcat 应用服务器中的两个不同应用程序无法访问同一个 Derby 副本,除非您使用 Derby 的 Client-Server 配置并配置一个 Derby Network Server。

【讨论】:

谢谢你回答我布莱恩!而且..如果访问derby db的元素是tomcat身份验证和管理db的应用程序,这种情况是否被视为单独的实例?换句话说......在我的情况下是否必须使用德比网络?非常感谢。

以上是关于如何为 tomcat 6 及其部署的 webapps 正确配置 JNDI?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 webapp 构建 phonegap 应用程序?

部署Tomcat及其负载均衡

Tomcat工作原理解析

tomcat部署项目-静态网页项目

如何为带有注释的 spring 设置 context.xml?

Tomcat服务器原理详解