JBoss JDBC MBean Предотвратить запуск, если сервер не найден
Во время запуска JBoss у меня есть Диспетчер постоянства, который зависит от соединения JDBC (DefaultDS). Соединение JDBC запускается нормально, независимо от того, может ли оно на самом деле подключиться к базе данных, поэтому при запуске Persistence Manager думает, что у него есть соединение. Затем он взрывается, потому что не может подключиться к базе данных и никогда не запускается. Это предотвращает запуск моего DestinationManager и вызывает все виды головной боли.
Есть ли способ заставить MBean-компоненты, которые зависят от соединения JDBC, не запускаться, если только соединение JDBC не может на самом деле соединиться с базой данных? В качестве альтернативы, есть ли способ сделать соединение JDBC зависимым от MBean, который активен только тогда, когда база данных может быть подключена?
ТЛ; др; Все, что мне нужно, это чтобы мой MBeans / DestinationManager ждал, пока база данных (DefaultDS) не станет доступной перед загрузкой.
Пожалуйста, прокомментируйте, если вам нужно больше информации об окружающей среде.
JBoss версия 4.2.3
База данных: MsSql
2 ответа
Если я правильно понимаю проблему, у вас есть проблема, потому что, хотя источник данных DefaultDS сообщает, что он запущен, так как он не установил никаких соединений, вы не обязательно знаете, что соединения могут быть установлены.
К сожалению, даже с включенной опцией prefill, служба источника данных по-прежнему будет запускаться нормально, даже если она не может установить соединение.
Лучше всего внедрить ServiceMBean, который проверяет фактическое соединение с источником данных, прежде чем он сообщит о запуске. В этом примере мы назовем его org.bob.ConnChecker и развернем с использованием ObjectName org.bob:service=ConnChecker.
Ваш дескриптор развертывания должен выглядеть примерно так:
<mbean code="org.bob.ConnChecker" name="jboss.mq:service=DestinationManager">
<depends optional-attribute-name="DataSource">jboss.jca:name=DefaultDS,service=ManagedConnectionPool</depends>
</mbean>
Таким образом, ваш сервис не будет запущен, пока не будет запущен источник данных. Ваша служба не запустится, если не сможет подключиться. Теперь вам просто нужно добавить org.bob:service=ConnChecker как зависимость DestinationManager:
jboss.mq:service=MessageCache jboss.mq:service=PersistenceManager jboss.mq:service=StateManager jboss.mq:service=ThreadPool jboss: service = Именование org.bob:service=ConnChecker
Код для ConnChecker будет выглядеть примерно так:
....
import org.jboss.system.ServiceMBeanSupport;
....
public class ConnChecker extends ServiceMBeanSupport implements ConnCheckerMBean {
/** The ObjectName of the data source */
protected ObjectName dataSourceObjectName = null;
/** The Datasource reference */
protected DataSource dataSource = null;
/**
* Called by JBoss when the dataSource has started
* @throws Exception This will happen if the dataSource cannot provide a connection
* @see org.jboss.system.ServiceMBeanSupport#startService()
*/
public void startService() throws Exception {
Connection conn = null;
try {
// Get the JNDI name from the DataSource Pool MBean
String jndiName = (String)server.getAttribute(dataSourceObjectName, "PoolJndiName");
// Get a ref to the DataSource from JNDI
lookupDataSource(jndiName);
// Try getting a connection
conn = dataSource.getConnection();
// If we get here, we successfully got a connection and this service will report being Started
} finally {
if(conn!=null) try { conn.close(); } catch (Exception e) {}
}
}
/**
* Configures the service's DataSource ObjectName
* @param dataSourceObjectName The ObjectName of the connection pool
*/
public void setDataSource(ObjectName dataSourceObjectName) {
this.dataSourceObjectName = dataSourceObjectName;
}
/**
* Acquires a reference to the data source from JNDI
* @param jndiName The JNDI binding name of the data source
* @throws NamingException
*/
protected void lookupDataSource(String jndiName) throws NamingException {
dataSource = (DataSource)new InitialContext().lookup(jndiName);
}
}
Код для ConnCheckerMBean выглядит следующим образом:
....
import org.jboss.system.ServiceMBeanSupport;
....
public interface ConnCheckerMBean extends ServiceMBean {
public void setDataSource(ObjectName dataSourceObjectName);
}
Таким образом, вы все равно будете получать ошибки, если не удастся установить соединение с базой данных, но DestinationManager не запустится, и, надеюсь, это будет лучше, чем головные боли, которые у вас сейчас есть.
Таким образом, нет никакого способа, чтобы куча бинов просто "ждала" и все еще позволяла Jboss загружаться до конца?
Не стандартным способом. Цикл загрузки JBoss либо завершается, либо сообщает об ошибке зависимости. Процесс последовательный и однопоточный (до JBoss 7).
Что вы могли бы сделать (и я только кратко проверил это):
- Повторно внедрите ConnChecker, чтобы запустить его проверку соединения в отдельном потоке. Он будет считаться запущенным, как только этот поток будет создан.
- Извлеките все XML-файлы конфигурации для служб, которые вы хотите зависеть от файлов ConnChecker (я полагаю, это будут все XML-файлы развертывания JMS), в другой каталог вне развертывания, например, / jboss / server / bob / late-deploy.
- Поскольку файлы позднего обслуживания в настоящее время отсутствуют в списке путей URLDeploymentScanner, они не будут развернуты как часть процесса развертывания по умолчанию.
Хитрость в том, чтобы получить файлы для позднего обслуживания для развертывания, заключается в том, что ваш новый ConnChecker будет счастливо вращаться, ожидая получения соединения (и, возможно, остановится и прекратит работу прямо там), но когда он успешно установит соединение, он выполнит код, который выглядит как это:
import javax.management.*;
.....
// The JBoss URL Deployment Scanner MBean ObjectName
ObjectName on = new ObjectName("jboss.deployment:flavor=URL,type=DeploymentScanner");
// server is the JBossMBean server. ServiceMBeans automatically have this reference.
server.invoke(on, "addURL", new Object[]{new URL("file:/jboss/server/bob/late-deploy")}, new String[]{String.class.getName});
Таким образом, это говорит сканеру развертывания "начать искать и в этом каталоге", и через пару секунд ваши поздние службы будут развернуты, надеюсь, без ошибок. Кроме того, поскольку вы добавили позднюю службу во время выполнения (и, следовательно, непостоянно), когда сервер перезапустится, сканер развертывания вернется к своей первоначальной конфигурации, ожидая, пока ConnChecker добавит в него новые URL-адреса.
Просто убедитесь, что для развертывания ScanEnabled установлено значение true и что ScanPeriod достаточно низок, чтобы вы получили необходимое время отклика для развертывания ваших поздних сервисов после установления соединения JDBC. Эта конфигурация MBean находится в
<jboss-home>/server/<server-name>/conf/jboss-service.xml
Ищите это:
<mbean code="org.jboss.deployment.scanner.URLDeploymentScanner"
name="jboss.deployment:type=DeploymentScanner,flavor=URL">
....
<!-- Frequency in milliseconds to rescan the URLs for changes -->
<attribute name="ScanPeriod">5000</attribute>
<!-- A flag to disable the scans -->
<attribute name="ScanEnabled">true</attribute>
....
</mbean>