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

Deployment 使数据源/资源成为部署时设置的正确方法,deployment,glassfish,jndi,war,Deployment,Glassfish,Jndi,War,我有一个需要两种设置的web应用程序: JDBC数据源 字符串标记 我非常希望能够将one.war部署到各种不同的容器(jetty、tomcat、gf3最小值),并在容器内的应用程序级别配置这些设置 我的代码执行以下操作: InitialContext ctx = new InitialContext(); Context envCtx = (javax.naming.Context) ctx.lookup("java:comp/env"); token = (String)envCtx.l

我有一个需要两种设置的web应用程序:

  • JDBC数据源
  • 字符串标记
我非常希望能够将one.war部署到各种不同的容器(jetty、tomcat、gf3最小值),并在容器内的应用程序级别配置这些设置

我的代码执行以下操作:

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>
...
请注意,
override=“false”
的意思正好相反。这意味着
web.xml
无法覆盖此设置

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


我想我对glassfish的期望会更高一些,因为它应该有一个完整的web管理界面,但我很乐意使用与上述功能相当的功能。

我不确定是否真正理解这个问题

作为一个例子,您可以在
web.xml
中以标准方式声明应用程序所需的资源

在部署时,应该遵循应用程序组件提供程序提供的说明来解决外部依赖关系(除其他事项外)例如,在应用服务器级别创建数据源,并通过使用特定于应用服务器的部署描述符(例如GlassFish的
sunweb.xml
)将其真实JNDI名称映射到应用程序使用的资源名称。显然,这是一个特定于容器的步骤,因此JavaEE规范没有涵盖

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

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

拥有一个管理界面并不会真正改变任何事情。如果我错过了什么,请毫不犹豫地告诉我。为了以防万一,您可以看看。

对于GF v3,您可能希望尝试利用asadmin的deploy子命令的--deploymentplan选项。在上讨论了这个问题。

我们在从Tomcat迁移到Glassfish 3时遇到了这个问题。以下是对我们有效的方法

  • 在Glassfish管理控制台中,为DEV/TEST/PROD/etc配置数据源(JDBC连接池和资源)
  • 在属性文件中记录您的部署时间参数(在我们的例子中是数据库连接信息)。例如:
  • 每个web应用都可以加载相同的数据库属性文件
  • 按如下方式查找JDBC资源

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

是否需要能够同时访问这两个数据源。。。来自同一台服务器?实际上可能不是,但我希望将它们都配置好。事实上,我们有一种合理的可能性需要两个数据源同时在live server上可用。我也有同样的问题,我还没有找到好的解决方案。我目前使用不同的GF域来部署我的应用程序,但这是次优解决方案,因为每个域都是操作系统进程,至少需要300 MB,而且很难管理多个域。我的问题是sun-web.xml在war中,作为应用程序的一部分部署,但不应该是因为它是特定于容器的。管理界面的唯一区别是,我认为应该有一种方法可以在每个web应用程序的基础上将映射更改为真实的JNDI名称。@Dreamon很遗憾,事情不是这样的,更改绑定不是一个非常常见的用例。如果您想这样做,您必须重新打包war。我认为应用程序组件提供程序应该提供一个.war(可能是一个无源的已签名、付费的.war),并且部署它不应该涉及重新打包。Tomcat可以做到我上面提到的。拥有一个管理界面不会改变任何东西,除了我在那里寻找一个配置选项,而不是类似于Tomcat的XML配置。我很惊讶其他人不想对测试和生产数据库使用一场战争。@Draemon我理解,但在这种情况下,您必须更改数据源配置。在这种情况下,@vkraemer建议的部署计划可能是你最好的选择。这并不完美,因为这是一个部署时间问题,但看起来相当不错,因为它保持了分离(允许部署纯EAR)。
<?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>
# Database connection properties
dev=jdbc/dbdev
test=jdbc/dbtest
prod=jdbc/dbprod

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();
 }