如何关闭在WildFly上正确定义为DataSource的嵌入式Derby

时间:2015-01-08 07:46:58

标签: derby wildfly

当我在WildFly上正常定义Derby DataSource时,db.lck文件保持未删除状态,表示每次关闭WildFly时数据库都没有正确关闭。因为嵌入式Derby需要一个特殊的关闭过程,该过程使用以“; shutdown = true”字符串结尾的JDBC URL获取新连接。

所以,我需要像shutdown-hook那样执行shutdown程序。我发现旧的JBoss有办法实现它:

https://developer.jboss.org/wiki/SetUpADerbyDatasource http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.jboss.jbossas/jboss-as-varia/6.0.0.Final/org/jboss/jdbc/DerbyDatabase.java

但我不知道如何在最近的WildFly上应用它,因为它看起来像“mbean”和“依赖”元素不再允许其数据源定义,我在最近的WildFly上找不到它的等价物。 / p>

我认为数据源定义的“connection-listener-class”变量是相当可观的,它可能是实现它的一种方法。我还没有尝试过,但它看起来有点复杂,我不确定它是否按预期工作。

那么,有没有办法定义一个shutdown-hook,用最近的WildFly执行Derby的shutdown程序?

修改

我发布了一条安装Apache Derby到WildFly的说明,其中包括我的解决方案。 http://www.nailedtothex.org/roller/kyle/entry/installing-apache-derby-to-wildfly

2 个答案:

答案 0 :(得分:2)

我找到了一个更好的MBean解决方案。它只是在每次WildFly关闭时执行关机程序。

只需克隆this repository并构建一个jar,将其放到$WILDFLY_HOME/standalone/deployments。项目中有各种文件,所以在这里粘贴所有文件很烦人。

对org.jboss.ironjacamar.jdbcadapters,connection-listener-class和connection-listener-property的依赖是不必要的,所以现在$WILDFLY_HOME/modules/org/apache/derby/main/module.xml可以简化如下:

module.xml

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="org.apache.derby">
    <resources>
        <resource-root path="derby.jar"/>
    </resources>
    <dependencies>
        <module name="javax.api"/>
        <module name="javax.transaction.api"/>
    </dependencies>
</module>

答案 1 :(得分:0)

connection-listener-class按照我的预期工作。我注册了一个监听器类,然后在每次关闭WildFly时,Derby都会正确启动关闭。

但是我应该记住一件事 - test-connection-in-pool不会触发连接监听器类。如果我只是启动WildFly,然后执行test-connection-in-pool到Derby的数据源,然后关闭WildFly,那么将永远不会调用侦听器并且db.lck将保持未删除状态。所以,它可能不是一个理想的解决方案。像更直接的shutdown-hook之类的东西会更好。

我所做的是:

  1. 把derby.jar,一个包含ConnectionListener实现和module.xml的jar放到$WILDFLY_HOME/modules/org/apache/derby/main
  2. 注册Derby的JDBC驱动程序(以下命令适用于jboss-cli)
    /subsystem=datasources/jdbc-driver=derby:add(driver-name=derby, driver-module-name=org.apache.derby, driver-class-name=org.apache.derby.jdbc.EmbeddedDriver)
  3. 注册数据源
    data-source add --name=DerbyDS --driver-name=derby --connection-url=jdbc:derby:/Users/kyle/tmp/derbytest --jndi-name=java:jboss/jdbc/DerbyDS --user-name=sa --password=sa
  4. 配置连接监听器类
    /subsystem=datasources/data-source=DerbyDS:write-attribute(name=connection-listener-class, value=org.nailedtothex.derby.DerbyShutdownConnectionListener)
  5. 配置connection-listener-property
    /subsystem=datasources/data-source=DerbyDS:write-attribute(name=connection-listener-property,value={"url"=>"jdbc:derby:/Users/kyle/tmp/derbytest"}
  6. module.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <module xmlns="urn:jboss:module:1.0" name="org.apache.derby">
        <resources>
            <resource-root path="derby.jar"/>
            <resource-root path="derby-shutdown-hook-1.0-SNAPSHOT.jar"/>
        </resources>
        <dependencies>
            <module name="javax.api"/>
            <module name="javax.transaction.api"/>
            <module name="org.jboss.ironjacamar.jdbcadapters"/>
        </dependencies>
    </module>
    

    DerbyShutdownConnectionListener.java

    Please refer GitHub for whole project contains pom.xml

    import org.jboss.jca.adapters.jdbc.spi.listener.ConnectionListener;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    public class DerbyShutdownConnectionListener implements ConnectionListener {
    
        private static final Logger log = Logger.getLogger(DerbyShutdownConnectionListener.class.getName());
        private static final String DEFAULT_URL = "jdbc:derby:";
        private static final String SHUTDOWN_SUFFIX = ";shutdown=true";
    
        private String url;
        private String urlForShutdown;
    
        public String getUrl() {
            return url;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        @Override
        synchronized public void initialize(final ClassLoader classLoader) throws SQLException {
            urlForShutdown = createUrlForShutdown();
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    log.log(Level.INFO, "Shutdown derby. URL to use: {0}", urlForShutdown);
                    shutdown(urlForShutdown);
                }
            });
            log.log(Level.INFO, "Derby shutdown hook added. URL to use: {0}", urlForShutdown);
        }
    
        private String createUrlForShutdown() {
            return (url == null ? DEFAULT_URL : url) + SHUTDOWN_SUFFIX;
        }
    
        private void shutdown(String url) {
            Connection cn = null;
            try {
                cn = DriverManager.getConnection(url);
            } catch (SQLException e) {
                if ("08006".equals(e.getSQLState()) || "XJ015".equals(e.getSQLState())) {
                    log.log(Level.INFO, "Derby shutdown succeeded. SQLState={0}", e.getSQLState());
                    return;
                }
                log.log(Level.SEVERE, "Derby shutdown failed", e);
            } finally {
                if (cn != null) {
                    try {
                        cn.close();
                    } catch (Exception e) {
                    }
                }
            }
        }
    
        @Override
        public void activated(Connection connection) throws SQLException {
        }
    
        @Override
        public void passivated(Connection connection) throws SQLException {
        }
    }