正确的方法使数据源/资源成为部署时设置

时间:2010-02-26 18:39:43

标签: deployment glassfish jndi war

我有一个需要两个设置的网络应用程序:

  • JDBC数据源
  • 字符串标记

我非常希望能够将一个.war部署到各种不同的容器(jetty,tomcat,gf3 minimum),并在容器内的应用程序级别配置这些设置。

我的代码执行此操作:

InitialContext ctx = new InitialContext();
Context envCtx = (javax.naming.Context) ctx.lookup("java:comp/env");
token = (String)envCtx.lookup("token");
ds = (DataSource)envCtx.lookup("jdbc/datasource")

我们假设我使用了glassfish管理界面来创建两个jdbc资源:jdbc / test-datasource和jdbc / live-datasource,它们连接到同一模式的不同副本,不同的服务器,不同的凭据等。说我想要将它部署到glassfish并将其指向测试数据源,我可能在sun-web.xml中有这个:

...
<resource-ref>
  <res-ref-name>jdbc/datasource</res-ref-name>
  <jndi-name>jdbc/test-datasource</jndi-name>
</resource-ref>
...

  • sun-web.xml in 我的战争,对吧?
  • 肯定必须有办法通过管理界面
  • 来做到这一点

我甚至试图做正确的事吗?其他容器能让这更容易吗?我特别感兴趣的是jetty 7如何处理这个问题,因为我将它用于开发。

编辑 Tomcat有一个合理的方法:

使用以下内容创建$TOMCAT_HOME/conf/Catalina/localhost/webapp.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context antiResourceLocking="false" privileged="true">
  <!-- String resource -->
  <Environment name="token" value="value of token" type="java.lang.String" override="false" />

  <!-- Linking to a global resource -->
  <ResourceLink name="jdbc/datasource1" global="jdbc/test" type="javax.sql.DataSource" />

  <!-- Derby -->
  <Resource name="jdbc/datasource2"
    type="javax.sql.DataSource"
    auth="Container"
    driverClassName="org.apache.derby.jdbc.EmbeddedDataSource"
    url="jdbc:derby:test;create=true"
    />

  <!-- H2 -->
  <Resource name="jdbc/datasource3"
    type="javax.sql.DataSource"
    auth="Container"
    driverClassName="org.h2.jdbcx.JdbcDataSource"
    url="jdbc:h2:~/test"
    username="sa"
    password=""
    />
</Context>

请注意,override="false"意味着相反。这意味着web.xml无法覆盖此设置

我喜欢这种方法,因为该文件是容器配置的一部分,而不是战争,但它不是全局配置的一部分;它是特定于webapp的。

我想我会期待更多来自glassfish,因为它应该有一个完整的网络管理界面,但我会很高兴与上述相同的东西。

3 个答案:

答案 0 :(得分:2)

对于GF v3,您可能希望尝试利用asadmin的deploy子命令的--deploymentplan选项。它在man page for the deploy subcommand上讨论。

答案 1 :(得分:2)

从Tomcat迁移到Glassfish 3时,我们遇到了这个问题。这对我们有用。

  • 在Glassfish管理控制台中,为DEV / TEST / PROD / etc配置数据源(JDBC连接池和资源)。
  • 在属性文件中记录部署时间参数(在我们的示例中为数据库连接信息)。例如:
# Database connection properties
dev=jdbc/dbdev
test=jdbc/dbtest
prod=jdbc/dbprod
  • 每个Web应用程序都可以加载相同的数据库属性文件。
  • 按如下方式查找JDBC资源。

import java.sql.Connection;
import javax.sql.DataSource;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * @param resourceName the resource name of the connection pool (eg jdbc/dbdev)
 * @return Connection a pooled connection from the data source 
 * associated with resourceName
 * @throws NamingException will be thrown if resource name is not found
 */
 public Connection getDatabaseConnection(String resourceName) 
             throws NamingException, SQLException {
    Context initContext = new InitialContext();
    DataSource pooledDataSource = (DataSource) initContext.lookup(resourceName);
    return pooledDataSource.getConnection();
 }

请注意,这是通常的两步过程,包括使用命名上下文“java:comp / env”进行查找。我不知道这是否适用于除GF3之外的应用程序容器,但在GF3中,使用上述方法时无需向web.xml添加资源描述符。

答案 2 :(得分:0)

我不确定真正理解这个问题/问题。

作为Application Component Provider,您可以在web.xml中以标准方式(容器不可知)声明应用程序所需的资源。

在部署时,Application Deployer and Administrator应遵循应用程序组件提供程序提供的指令来解析外部依赖性(以及其他内容),例如通过在应用程序中创建数据源服务器级别,并通过使用特定于应用程序服务器的部署描述符(例如,GlassFish的sun-web.xml)将其真实JNDI名称映射到应用程序使用的资源名称。显然,这是一个容器特定的步骤,因此不受Java EE规范的约束。

现在,如果要更改应用程序正在使用的数据库,则必须:

  • 更改应用程序服务器部署描述符中的映射 - 或 -
  • 修改现有数据源的配置,使其指向另一个数据库。

拥有管理界面并没有真正改变任何东西。如果我错过了什么,请不要犹豫,让我知道。为了以防万一,也许看看this previous answer