Правильный способ сделать источники данных/ресурсы параметром времени развертывания

StackOverflow https://stackoverflow.com/questions/2343976

Вопрос

У меня есть веб-приложение, которое требует двух настроек:

  • Источник данных JDBC
  • Строковый токен

Я отчаянно хочу иметь возможность развертывать один .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>
...

но

  • sun-web.xml идет внутри моя война, да?
  • наверняка должен быть способ сделать это через интерфейс управления

Пытаюсь ли я поступить правильно?Другие контейнеры облегчают задачу?Мне было бы особенно интересно, как с этим справится 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.

Мне нравится этот подход, потому что файл является частью контейнер конфигурация не война, но она не является частью глобальной конфигурации;это специфично для веб-приложения.

Думаю, я ожидаю немного большего от glassfish, поскольку он должен иметь полноценный интерфейс веб-администратора, но я был бы вполне доволен чем-то эквивалентным вышеописанному.

Нет правильного решения

Другие советы

Для GF v3 вы можете попробовать использовать параметр --deploymentplan подкоманды развертывания asadmin.Это обсуждается на man-страница для подкоманды развертывания.

У нас возникла именно эта проблема при переходе с Tomcat на Glassfish 3.Вот что работает для нас.

  • В консоли администратора Glassfish настройте источники данных (пулы соединений и ресурсы JDBC) для DEV/TEST/PROD/и т. д.
  • Запишите параметры времени развертывания (в нашем случае информацию о подключении к базе данных) в файл свойств.Например:
# Database connection properties
dev=jdbc/dbdev
test=jdbc/dbtest
prod=jdbc/dbprod
  • Каждое веб-приложение может загружать один и тот же файл свойств базы данных.
  • Найдите ресурс 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 при использовании вышеуказанного подхода.

Я не уверен, что действительно понимаю вопрос/проблему.

Как Поставщик компонентов приложения, вы объявляете ресурсы, необходимые вашему приложению, в стандартный способ (независимо от контейнера) в web.xml.

Во время развертывания Развертыватель и администратор приложений должен следовать инструкциям, предоставленным Поставщик компонентов приложения для разрешения внешних зависимостей (помимо прочего), например, путем создания источника данных на уровне сервера приложений и сопоставления его реального имени JNDI с именем ресурса, используемого приложением, посредством использования дескриптора развертывания, конкретного сервера приложений (например,тот sun-web.xml для GlassFish).Очевидно, это специфичный для контейнера шаг и, следовательно, не подпадает под спецификацию Java EE.

Теперь, если вы хотите изменить базу данных, которую использует приложение, вам придется либо:

  • изменить сопоставление в дескрипторе развертывания сервера приложений - или -
  • измените конфигурацию существующего источника данных, чтобы он указывал на другую базу данных.

Наличие интерфейса администратора ничего не меняет.Если я что-то пропустил, не стесняйтесь, дайте мне знать.И на всякий случай, возможно, посмотрите этот предыдущий ответ.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top