40

We're using hdsqldb in memory to run junit tests which operate against a database. The db is setup before running each test via a spring configuration. All works fine. Now when a tests fails it can be convinient to be able to inspect the values in the in memory database. Is this possible? If so how? Our url is:

jdbc.url=jdbc:hsqldb:mem:testdb;sql.enforce_strict_size=true

The database is destroyed after each tests. But when the debugger is running the database should also still be alive. I've tried connecting with the sqldb databaseManager. That works, but I don't see any tables or data. Any help is highly appreciated!

Albert
  • 2,055
  • 1
  • 18
  • 23

8 Answers8

71

In your unit test or in the @Before / setUp() method, you can add the following line to launch the HSQL Database Manager:


org.hsqldb.util.DatabaseManager.main(new String[] {
  "--url",  "jdbc:hsqldb:mem:testdb", "--noexit"
});

or for the improved Swing version with "more refinements" (but about same functionality)


org.hsqldb.util.DatabaseManagerSwing.main(new String[] {
  "--url",  "jdbc:hsqldb:mem:testdb", "--noexit"
});

The DB manager lets you inspect your schema and run SQL queries on the live in-memory database while the application is running.

Make sure to set a beakpoint or pause the execution one way or another if you want to check the state of your database at a specific line.

rogerdpack
  • 50,731
  • 31
  • 212
  • 332
dimdm
  • 1,121
  • 1
  • 9
  • 13
  • Note that I omitted the "sql.enforce_strict_size=true" part of the JDBC URL, I'm unsure what the effect would be here... – dimdm Jul 26 '10 at 15:07
  • 6
    When I do as you suggested the DatabaseManager starts, but freezes. I cannot do anything with it. If I force quit it, the debug session dies as well. I'm using Intellij Idea 11.1.2. – Paul D. Eden Jul 11 '12 at 14:57
  • 3
    See here (http://stackoverflow.com/questions/11435654/connect-to-in-memory-hsql-hypersonic-database-with-databasemanager-while-debug/11437102#11437102) for a discussion on how to keep DatabaseManager from freezing. – Paul D. Eden Jul 11 '12 at 16:25
  • Note that this doesn't work when running a remote debugging session on Tomcat. – jricher Dec 03 '12 at 22:11
  • 1
    @jricher Tomcat doesn't prevent the GUI from launching. You will have to VNC into the remote host to use it though. But you are right, this doesn't allow the database manager and the in-memory DB to run on different VMs. – dimdm Dec 11 '12 at 21:43
  • More to the point, most tomcat instances that I use (and that probably many others use) are launched in a headless environment, which precludes the use of this technique. – jricher Dec 14 '12 at 20:50
  • 5
    Note that I had to add to my `@Before` method the line `System.setProperty("java.awt.headless", "false")` in order to prevent `java.awt.HeadlessException` from being thrown (even when on windows dev machine) – kumetix Mar 30 '16 at 13:02
  • This tool is from 2010 and have a lot of limitations. Is there newer alternatives? – Dherik Sep 14 '17 at 12:39
  • @kumetix was that from within Tomcat, I presume yes? – rogerdpack Oct 30 '20 at 17:00
  • @Dherik not built-in with HSQLDB but you could use some other in memory manager that can use a JDBC connection I suppose... – rogerdpack Nov 03 '20 at 16:25
17

HSQL is in memory, so when you say that you're connecting with SQLDB Database Manager, you're not - you are instead connecting to another database in the memory space of the SQLDB Database Manager, not the one in the memory space of the unit test. This is why the database in the SQLDB Database Manager is empty.

You can run HSQL as a server using org.hsqldb.Server as described here.

Although the org.hsqldb.Server class is typically used to start-up a seperate process, you could instantiate and configure it in your unit test, which should allow a remote process to connect and query the database.

Alternatively, you'll have to write some sort of dump functionality that is called from within your unit test as need be.

As an aside, using HSQL in unit tests is just proving your code works against HSQL, which is different to the actual database. This means you can get false positives and vice versa. The same thing can be achieved with a mocking API or better, save the database testing for some decent integration tests that works with the real database.

Nick Holt
  • 31,429
  • 4
  • 46
  • 56
  • 1
    Thanks for your response! I've figured it out and it works if you have hsqldb write to file and use that url to connect to it. I was using an older driver which was in my way. I agree that you should also test it against a real database which we also do, but having the sql queries beeing validated is more valuable then mocking it away I'd say. – Albert Apr 23 '10 at 11:28
  • The website mentioned in the answer is giving 404. – Saurabh Oza Nov 22 '18 at 07:18
  • 1
    @SaurabhOza fixed :-) – Nick Holt Nov 26 '18 at 16:19
15

Run your unit test to a breakpoint, then in the Debug perspective of Eclipse, open the Display view (Window, Show View, Display) and enter

    org.hsqldb.util.DatabaseManagerSwing.main(new String[] {
  "--url",  "jdbc:hsqldb:mem:testdb", "--noexit"
});

(as per dimdm's post), highlight it, right-click and choose Execute.

enter image description here

rogerdpack
  • 50,731
  • 31
  • 212
  • 332
Gwaptiva
  • 343
  • 3
  • 11
1

You could also use the DatabaseManagerSwing class included in [HSQLDB][1] passing to it an open connection, that allows you to see the state of the database in the transaction the connection is in.

DatabaseManagerSwing manager = new DatabaseManagerSwing();
manager.main();
manager.connect(connection);
manager.start();
mic.sca
  • 1,602
  • 2
  • 20
  • 33
1

The above accepted answer works perfectly only if the database name, username and password is untouched (testdb, SA, blank password).

For custom database name, username and password you will get the following exception

java.sql.SQLInvalidAuthroizationSpecException: invalid authorization specification - not found: SA

Then, you have to connect manually.

To connect directly to a non "default" DB use the following snippet

org.hsqldb.util.DatabaseManager.main(new String[] {
  "--url",  "jdbc:hsqldb:mem:yourdbname", "--noexit",
  "--user", "dbusername", "--password", "dbpassword"
});

or for the improved Swing version

org.hsqldb.util.DatabaseManagerSwing.main(new String[] {
  "--url",  "jdbc:hsqldb:mem:yourdbname", "--noexit",
  "--user", "dbusername", "--password", "dbpassword"
});

Before executing the above snippet update the following

  • yourdbname - Update yourdbname with real database name
  • dbusername - Update dbusername with your database username
  • dbpassword - Update dbpassword with your database password
rogerdpack
  • 50,731
  • 31
  • 212
  • 332
1

The problem with the database-manager freezing can be resolved by starting the database-manager in a new thread, and sleeping the thread the test runs on.

Add this code snippet to your test and you will be able to inspect the database while debugging. Remember to change the database-url to your database.

Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            org.hsqldb.util.DatabaseManagerSwing.main(new String[] {
                    "--url",  "jdbc:hsqldb:mem://localhost:9001", "--noexit"
            });
        }
    });

t.start();

try {
    Thread.sleep(10000000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
Marius Kohmann
  • 485
  • 1
  • 5
  • 9
  • You don't need a new thread for the DatabaseManagerSwing. And then you'll have your teat frozen at that sleep :| I do like the `sleep` call to keep it from freezing though, without having to modify the debugger :) – rogerdpack Nov 03 '20 at 17:50
0

If you know the table you want to "inspect" at any point you can output its current values to the console.

https://stackoverflow.com/a/31887249/32453

You could even do this call in a debugger...

rogerdpack
  • 50,731
  • 31
  • 212
  • 332
0

This worked for me:

DatabaseManager.threadedDBM();
Thread.sleep(Long.MAX_VALUE);

from https://stackoverflow.com/a/13732467/32453

It's just the "non swing" variety DatabaseManager and prompts you for a JDBC connection string. The swing one doesn't have an equivalent method I don't think.

rogerdpack
  • 50,731
  • 31
  • 212
  • 332