This version of the manual is outdated. For the latest version, follow this link: http://www.jooq.org/doc/3.0/manual.

The jOOQ User Manual. Multiple Pages : Advanced topics : Execute listeners and the jOOQ Consoleprevious : next

# ExecuteListener

The jOOQ Factory Settings let you specify a list of org.jooq.ExecuteListener classes. The ExecuteListener is essentially an event listener for Query, Routine, or ResultSet render, prepare, bind, execute, fetch steps. It is a base type for loggers, debuggers, profilers, data collectors. Advanced ExecuteListeners can also provide custom implementations of Connection, PreparedStatement and ResultSet to jOOQ in apropriate methods. For convenience, consider extending org.jooq.impl.DefaultExecuteListener instead of implementing this interface.

Here is a sample implementation of an ExecuteListener, that is simply counting the number of queries per type that are being executed using jOOQ:

package com.example;

public class StatisticsListener extends DefaultExecuteListener {
    public static Map<ExecuteType, Integer> STATISTICS = new HashMap<ExecuteType, Integer>();

    // Count "start" events for every type of query executed by jOOQ
    @Override
    public void start(ExecuteContext ctx) {
        Integer count = STATISTICS.get(ctx.type());

        if (count == null) {
            count = 0;
        }

        STATISTICS.put(ctx.type(), count + 1);
    }
}

Now, configure jOOQ's runtime to load your listener

<settings>
  <executeListeners>
    <executeListener>com.example.StatisticsListener</executeListener>
  </executeListeners>
</settings>

And log results any time with a snippet like this:

log.info("STATISTICS");
log.info("----------");

for (ExecuteType type : ExecuteType.values()) {
    log.info(type.name(), StatisticsListener.STATISTICS.get(type) + " executions");
}

This may result in the following log output:

15:16:52,982  INFO - TEST STATISTICS
15:16:52,982  INFO - ---------------
15:16:52,983  INFO - READ                     : 919 executions
15:16:52,983  INFO - WRITE                    : 117 executions
15:16:52,983  INFO - DDL                      : 2 executions
15:16:52,983  INFO - BATCH                    : 4 executions
15:16:52,983  INFO - ROUTINE                  : 21 executions
15:16:52,983  INFO - OTHER                    : 30 executions

Please read the ExecuteListener Javadoc for more details

# jOOQ Console

The ExecuteListener API was driven by a feature request by Christopher Deckers, who has had the courtesy to contribute the jOOQ Console, a sample application interfacing with jOOQ's ExecuteListeners. The jOOQ Console logs all queries executed by jOOQ and displays them nicely in a Swing application. With the jOOQ Console's logger, you can:

A short overview of such a debugging session can be seen here:

jOOQ Console example

Please note that the jOOQ Console is still experimental. Any feedback is very welcome on the jooq-user group

# jOOQ Console operation modes

The jOOQ Console can be run in two different modes:

Both modes will require that you set the org.jooq.debug.DebugListener in the Factory's settings. When using XML settings:

<settings>
  <executeListeners>
    <executeListener>org.jooq.debug.DebugListener</executeListener>
  </executeListeners>
</settings>

Or when using programmatic settings:

Settings settings = new Settings()
    .getExecuteListeners().add("org.jooq.debug.DebugListener");
Factory factory = new Factory(connection, dialect, settings);

# In-process mode

The in-process mode is useful for Swing applications or other, locally run Java programs accessing the database via jOOQ. In order to launch the jOOQ Console "in-process", specify the previously documented settings and launch the Console as follows:

// Define a DatabaseDescriptor for the "in-process" mode
// It is needed for the "Editor" tab
DatabaseDescriptor descriptor = new DatabaseDescriptor() {

    // Return your generated schema. This is used by the console
    // to introspect your schema data
    @Override
    public Schema getSchema() {
        return com.example.MySchema.MY_SCHEMA;
    }

    // Return the SQL dialect that you're using
    @Override
    public SQLDialect getSQLDialect() {
        return SQLDialect.ORACLE;
    }

    // Return a connection
    @Override
    public Connection createConnection() {
        try {
            return DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "test", "test");
        }
        catch (Exception ignore) {}
    }
};

// Now pass this database descriptor to the Console and make it visible
try {

    // Use this for a nicer look-and-feel
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

    // Create a new Console
    Console console = new Console(descriptor, true);
    console.setLoggingActive(true);
    console.setVisible(true);
}
catch (Exception ignore) {}

Only in the in-process mode, you can execute ad-hoc queries directly from the console, if you provide it with proper DatabaseDescriptor. These queries are executed from the Editor pane which features:

jOOQ Console example

# "Headless" mode

In J2EE or other server/client environments, you may not be able to run the console in the same process as your application. You can then run the jOOQ Console in "headless" mode. In addition to the previously documented settings, you'll have to start a debugger server in your application process, that the console can connect to:

// Create a new RemoteDebuggerServer in your application that listens to
// incoming connections on a given port
SERVER = new RemoteDebuggerServer(DEBUGGER_PORT);

Now start your application along with the debugger server and launch the console with this command:

java -jar jooq-console-2.1.0.jar [host] [port]

Depending on your distribution, you may have to manually add rsyntaxtextarea-1.5.0.jar and jOOQ artefacts on your classpath.


The jOOQ User Manual. Multiple Pages : Advanced topics : Execute listeners and the jOOQ Consoleprevious : next

Fork me on GitHub
The jOOQ Logo