Правильный способ сделать источники данных/ресурсы параметром времени развертывания
-
23-09-2019 - |
Вопрос
У меня есть веб-приложение, которое требует двух настроек:
- Источник данных 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.
Теперь, если вы хотите изменить базу данных, которую использует приложение, вам придется либо:
- изменить сопоставление в дескрипторе развертывания сервера приложений - или -
- измените конфигурацию существующего источника данных, чтобы он указывал на другую базу данных.
Наличие интерфейса администратора ничего не меняет.Если я что-то пропустил, не стесняйтесь, дайте мне знать.И на всякий случай, возможно, посмотрите этот предыдущий ответ.