如果找不到服务器,JBoss JDBC MBean会阻止启动

时间:2011-07-20 15:11:31

标签: jdbc jboss mbeans persistence-manager

在JBoss启动期间,我有一个依赖于JDBC连接(DefaultDS)的持久性管理器。无论JDBC连接是否可以实际连接到数据库,JDBC连接都可以正常运行,因此当Persistence Manager启动时,它认为它具有连接。然后它爆炸,因为它无法连接到数据库,永远不会启动。这可以防止我的DestinationManager启动并引起各种各样的头痛。

有没有办法让依赖于JDBC连接的MBean不启动,除非JDBC连接实际上可以连接到数据库?作为替代方案,有没有办法使JDBC连接依赖于只在数据库可以连接时才有效的MBean?

TL;博士;我需要的只是让我的MBeans / DestinationManager等到数据库(DefaultDS)在启动之前可用。

如果您需要有关环境的更多信息,请发表评论。

  • JBoss版本4.2.3

  • 数据库:MsSql

2 个答案:

答案 0 :(得分: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的:服务=命名     org.bob:服务= 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将无法启动,并且希望这比您现在遇到的麻烦更好。

答案 1 :(得分:2)

  

所以没有办法让一堆豆只是“等待”而且仍然存在   让Jboss一路启动?

不是任何标准方式。 JBoss引导周期要么运行完成,要么报告依赖性故障。该过程是顺序和单线程的(直到JBoss 7)。

你能做什么(我只是简单地测试过这个)是:

  • 重新实施 ConnChecker 以在单独的线程中运行其连接测试。一旦该线程产生,它将被视为已启动。
  • 将您希望依赖 ConnChecker (我想这将是所有JMS部署XML)文件的所有XML配置文件拉出到 deploy 之外的另一个目录中,例如 / 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>