YuLimin 发表于 2013-1-30 02:05:46

可重用的 Hsqldb 启动、停止之 Ant 任务脚手架

可重用的 Hsqldb 启动、停止之 Ant 任务脚手架

在Eclipse里用Ant来启动Hsqldb
      <!-- Start the Hsqldb database server -->      <targetname="dbstart"description="Start the Hsqldb database server">            <javaclassname="org.hsqldb.Server"fork="yes"classpathref="hsqldb.classpath"failonerror="true">                  <argvalue="-database.0"/>                  <argvalue="file:${database.dir}/db"/>            </java>      </target>
此时如果要停止 Hsqldb ,即点击红色按钮来 Terminate 掉它,实现上,Hsqldb的Java线程还是在后台运行的,它并没有真正结束。

判断的方法有四种:
1、再次运行 ant startdb 任务,会发现 db.lck 还被使用,而 <delete dir="${database.dir}"/> 删除不了,被前一个实例 Lock 住了。
Buildfile: xxx\build.xml
startdb:
    Deleting directory xxx\database

BUILD FAILED
xxx\build.xml:88: Unable to delete file xxx\database\db.lck

2、利用JDK 5.0以上的版本中的 jps 来查看,即:
%JAVA_HOME%/bin/jps -lvm
你可以看到其中有如下的信息显示
<pid> org.hsqldb.Server -database.0 file:database/db
即表明它还是在运行当中。

3、netstat -a | find "9001"
TCP    XXX:9001   XXX:0 LISTENING
发现 Hsqldb 默认的服务端口 9001 还在监听中。

4、再次运行你的数据库连接程序,程序运行正常,还是可以连接上去,并可以完全正常进行你的数据操作。
由上面的方法可见它还是在正常运行中,Eclipse里的红色按钮并没有真正 Terminate 掉它。

那如何真正停止掉它呢?同样也有几种方法。
1、利用 Ant 本身提供的 sql 任务,如下发送 SHUTDOWN 命令过去就可以了,如下:
      <!-- Shutdown the Hsqldb database server via Ant sql Task -->      <targetname="dbshutdown"description="Shutdown the Hsqldb database server via Ant sql Task">            <echomessage="Ignore the message:'java.sql.SQLException: Connection is broken: java.io.EOFException', Don't care about it."/>            <sqldriver="org.hsqldb.jdbcDriver"url="jdbc:hsqldb:hsql://localhost/"userid="sa"password=""classpathref="hsqldb.classpath"onerror="stop"print="true"><!]></sql>      </target>
但是虽然这个可以让 Hsqldb Server 停止掉了,但是会报错误,build出现错误我是不能接受的,不知道你是否接受?
shutdowndb:
    Ignore the message:'java.sql.SQLException: Connection is broken: java.io.EOFException', Don't care about it.
       Executing commands
       0 rows affected

BUILD FAILED
xxx\build.xml:124: java.sql.SQLException: Connection is broken: java.io.EOFException

打开 verbose 选项看一看更加详细的信息:
shutdowndb:
    Ignore the message:'java.sql.SQLException: Connection is broken: java.io.EOFException', Don't care about it.
       connecting to jdbc:hsqldb:hsql://localhost/
       Loading org.hsqldb.jdbcDriver using AntClassLoader with classpath xxx\lib\hsqldb.jar

BUILD FAILED
java.sql.SQLException: socket creation error
      at org.apache.tools.ant.taskdefs.JDBCTask.getConnection(JDBCTask.java:314)
      at org.apache.tools.ant.taskdefs.SQLExec.execute(SQLExec.java:346)
      at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)
      at org.apache.tools.ant.Task.perform(Task.java:364)
      at org.apache.tools.ant.Target.execute(Target.java:341)
      at org.apache.tools.ant.Target.performTasks(Target.java:369)
      at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1216)
      at org.apache.tools.ant.Project.executeTarget(Project.java:1185)
      at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:40)
      at org.apache.tools.ant.Project.executeTargets(Project.java:1068)
      at org.apache.tools.ant.Main.runBuild(Main.java:668)
      at org.apache.tools.ant.Main.startAnt(Main.java:187)
      at org.apache.tools.ant.launch.Launcher.run(Launcher.java:246)
      at org.apache.tools.ant.launch.Launcher.main(Launcher.java:67)
Caused by: java.sql.SQLException: socket creation error
      at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
      at org.hsqldb.jdbc.jdbcConnection.<init>(Unknown Source)
      at org.hsqldb.jdbcDriver.getConnection(Unknown Source)
      at org.hsqldb.jdbcDriver.connect(Unknown Source)
      at org.apache.tools.ant.taskdefs.JDBCTask.getConnection(JDBCTask.java:304)
      ... 13 more
--- Nested Exception ---
java.sql.SQLException: socket creation error
      at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
      at org.hsqldb.jdbc.jdbcConnection.<init>(Unknown Source)
      at org.hsqldb.jdbcDriver.getConnection(Unknown Source)
      at org.hsqldb.jdbcDriver.connect(Unknown Source)
      at org.apache.tools.ant.taskdefs.JDBCTask.getConnection(JDBCTask.java:304)
      at org.apache.tools.ant.taskdefs.SQLExec.execute(SQLExec.java:346)
      at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)
      at org.apache.tools.ant.Task.perform(Task.java:364)
      at org.apache.tools.ant.Target.execute(Target.java:341)
      at org.apache.tools.ant.Target.performTasks(Target.java:369)
      at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1216)
      at org.apache.tools.ant.Project.executeTarget(Project.java:1185)
      at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:40)
      at org.apache.tools.ant.Project.executeTargets(Project.java:1068)
      at org.apache.tools.ant.Main.runBuild(Main.java:668)
      at org.apache.tools.ant.Main.startAnt(Main.java:187)
      at org.apache.tools.ant.launch.Launcher.run(Launcher.java:246)
      at org.apache.tools.ant.launch.Launcher.main(Launcher.java:67)

也就是说在执行 SHUTDOWN 命令后,
org.apache.tools.ant.taskdefs.JDBCTask.getConnection(JDBCTask.java:314) 还去 getConnection,那肯定就出错了。

2、自己写个简单的 Ant 脚本来关闭它
ShutdownTask.java
import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.sql.Statement;import org.apache.tools.ant.BuildException;import org.apache.tools.ant.Task;/** *ShutdownTask:AntTaskforshutdowntheHsqldbserver. * *@authorYuLimin */publicclass ShutdownTask extends Task{      // Defaut Value      private String msg = "ShutdownTask";      private String driver = "org.hsqldb.jdbcDriver";      private String url = "jdbc:hsqldb:hsql://localhost/";      private String userid = "sa";      private String password = "";      private String sqlCommand = "SHUTDOWN";      public ShutdownTask()      {            super();      }      /**       *ForTest       *       *@paramargv       *@throwsException       */      publicstaticvoid main(final String[] argv)      {            final ShutdownTask shutdownTask = new ShutdownTask();            shutdownTask.shutdown();      }      /**       *Themethodexecutingthetask       */      publicvoid execute() throws BuildException      {            System.out.println(msg + " Begin......");            System.out.println("Driver=" + getDriver());            System.out.println("URL=" + getUrl());            System.out.println("Userid=" + getUserid());            System.out.println("Password=" + getPassword());            System.out.println("SqlCommand=" + getSqlCommand());            shutdown();            System.out.println(msg + " End......");            System.out.println();      }      /**       *Shutdownthedatabase       */      publicvoid shutdown()      {            Connection connection = null;            Statement statement = null;            try            {                  Class.forName(getDriver());                  connection = DriverManager.getConnection(getUrl(),getUserid(),getPassword());                  statement = connection.createStatement();                  statement.execute(getSqlCommand());                  statement.close();                  connection.close();            }            catch(Exception e)            {                  e.printStackTrace();                  thrownew RuntimeException(e);            }            finally            {                  if(statement != null)                  {                        try                        {                              statement.close();                        }                        catch(SQLException e)                        {                              thrownew RuntimeException(e);                        }                  }                  if(connection != null)                  {                        try                        {                              connection.close();                        }                        catch(SQLException e)                        {                              thrownew RuntimeException(e);                        }                  }            }      }      // More accessor method : setter & getter      publicvoid setMsg(final String msg)      {            this.msg = msg;      }      publicvoid setDriver(final String driver)      {            this.driver = driver;      }      publicvoid setPassword(final String password)      {            this.password = password;      }      publicvoid setUrl(final String url)      {            this.url = url;      }      publicvoid setUserid(final String userid)      {            this.userid = userid;      }      publicvoid setSqlCommand(final String sqlCommand)      {            this.sqlCommand = sqlCommand;      }      public String getDriver()      {            returndriver;      }      public String getPassword()      {            returnpassword;      }      public String getUrl()      {            returnurl;      }      public String getUserid()      {            returnuserid;      }      public String getSqlCommand()      {            returnsqlCommand;      }      public String getMsg()      {            returnmsg;      }}
编译 javac -classpath %ANT_HOME%/lib/ant.jar ShutdownTask.java
打包 jar cvf ShutdownTask.jar *.*
把 ShutdownTask.jar 直接放到项目的lib目录下,下面的示例 classpath 我直接引入到 hsqldb.classpath中,可以根据需要放到项目的不同地方再进行调整引入使用等等。。。:)

build.xml里的调用示例,爱怎么用就怎么用,提供好几个示例。
      <!-- Classpath declaration -->      <pathid="hsqldb.classpath">            <filesetdir="${lib.dir}">                  <includename="**/hsqldb.jar"/>                  <includename="**/ShutdownTask.jar"/>            </fileset>      </path>      <!-- Shutdown the Hsqldb database server via ShutdownTask -->      <targetname="dbshutdownTask"description="Shutdown the Hsqldb database server via ShutdownTask">            <!-- Define ShutdownTask -->            <taskdefname="shutdownTask"classname="ShutdownTask"classpathref="hsqldb.classpath"/>            <!-- Call ShutdownTask -->            <!-- Default ShutdownTask, only like this -->            <!-- <shutdownTask/> -->            <!-- Sample MyShutdownTask -->            <!-- <shutdownTask driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:hsql://localhost/" userid="sa" password="" sqlCommand="SHUTDOWN" msg="MyShutdownTask"/> -->            <!-- Sample MyShutdownTask SHUTDOWN COMPACT -->            <!-- <shutdownTask driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:hsql://localhost/" userid="sa" password="" sqlCommand="SHUTDOWN COMPACT" msg="MyShutdownTask"/> -->            <!-- Sample MyShutdownTask SHUTDOWN IMMEDIATELY -->            <shutdownTaskdriver="org.hsqldb.jdbcDriver"url="jdbc:hsqldb:hsql://localhost/"userid="sa"password=""sqlCommand="SHUTDOWN IMMEDIATELY"msg="MyShutdownTask"/>      </target>
3、就在直接在命令行下运行 ant startdb ,然后 Ctrl + C 直接干掉它就可以。
            如启动时的提示:From command line, use + to abort abruptly

补充
OS:Windows 2K Pro SP4 English
ant -version
Apache Ant version 1.6.5 compiled on June 2 2005

JDK 1.4.2 1.5.0 1.6.0 1.7.0都可以。。。

最后,如何使用它呢?
在其它项目中只要相应地 import 这个 build.xml 这个文件即可达到重用,如:新项目与这个项目并行,即
<?xml version="1.0" encoding="utf-8"?><projectname="JPA_OtherProject"default="compile"basedir=".">      <import file="../Common/build.xml" />    ......
也可以建立 build.properties 资源文件来配置一些信息等等。。。
附上完整的 build.xml 与 ShutdownTask.jar 以及 Eclipse项目文件,import 到 Eclipse 中,把 build.xml 拖到Ant视图里,直接就可以用了。

BTW:刚才从Word里拷贝过来提交,JavaEye的有BUG,现在重新修改了一下!!!
页: [1]
查看完整版本: 可重用的 Hsqldb 启动、停止之 Ant 任务脚手架