Skip to content
Permalink
Browse files

[jdbc-driver] JDBC transaction handlers (#90)

  • Loading branch information...
cchantep committed Sep 21, 2018
1 parent 4b4f08f commit f18cf9459e071d00b1c7cbb810b44a78dfc4bd2d
@@ -204,6 +204,10 @@ public void commit() throws SQLException {
if (this.autoCommit) {
throw new SQLException("Auto-commit is enabled");
} // end of if

// ---

handler.getResourceHandler().whenCommitTransaction(this);
} // end of

/**
@@ -215,6 +219,10 @@ public void rollback() throws SQLException {
if (this.autoCommit) {
throw new SQLException("Auto-commit is enabled");
} // end of if

// ---

handler.getResourceHandler().whenRollbackTransaction(this);
} // end of rollback

/**
@@ -14,24 +14,56 @@
*/
public StatementHandler getStatementHandler();

// --- Inner classes ---
/**
* Returns resource handler.
* @return the resource handler
*/
public ResourceHandler getResourceHandler();

/**
* Returns this connection handler with its resource |handler| updated.
*
* @param handler the new resource handler
*/
public ConnectionHandler withResourceHandler(ResourceHandler handler);

// --- Inner classes ---

/**
* Default implementation.
*/
public static final class Default implements ConnectionHandler {
final StatementHandler stmtHandler;
final ResourceHandler resHandler;

/**
* Statement constructor.
*
* @param stmtHandler the statement handler
*/
public Default(final StatementHandler stmtHandler) {
this(stmtHandler, new ResourceHandler.Default());
}

/**
* Bulk constructor.
* @param handler the statement handler
*
* @param stmtHandler the statement handler
* @param resHandler the resource handler
*/
public Default(final StatementHandler handler) {
if (handler == null) {
throw new IllegalArgumentException();
public Default(final StatementHandler stmtHandler,
final ResourceHandler resHandler) {

if (stmtHandler == null) {
throw new IllegalArgumentException("Statement handler");
} // end of if

this.stmtHandler = handler;
if (resHandler == null) {
throw new IllegalArgumentException("Resource handler");
} // end of if

this.stmtHandler = stmtHandler;
this.resHandler = resHandler;
} // end of <init>

/**
@@ -40,5 +72,19 @@ public Default(final StatementHandler handler) {
public StatementHandler getStatementHandler() {
return this.stmtHandler;
} // end of getStatementHandler

/**
* {@inheritDoc}
*/
public ResourceHandler getResourceHandler() {
return this.resHandler;
} // end of getResourceHandler

/**
* {@inheritDoc}
*/
public ConnectionHandler withResourceHandler(ResourceHandler handler) {
return new Default(this.stmtHandler, handler);
} // end of withResourceHandler
} // end of class DefaultHandler
} // end of interface ConnectionHandler
@@ -180,7 +180,6 @@ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
* @see #connection(acolyte.jdbc.ConnectionHandler)
*/
public static acolyte.jdbc.Connection connection(final ConnectionHandler handler, final Properties info) {

if (handler == null) {
throw new IllegalArgumentException();
} // end of if
@@ -211,12 +210,31 @@ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
* @throws IllegalArgumentException if handler is null
*/
public static acolyte.jdbc.Connection connection(final StatementHandler handler, final Properties info) {
return connection(handler, new ResourceHandler.Default(), info);
} // end of connection

if (handler == null) {
throw new IllegalArgumentException();
/**
* Direct connection, with given |handler| and random URL.
*
* @param stmtHandler the statement handler
* @param resHandler the resource handler
* @param info Connection properties (optional)
* @return the configured connection
* @throws IllegalArgumentException if handler is null
*/
public static acolyte.jdbc.Connection connection(final StatementHandler stmtHandler, final ResourceHandler resHandler, final Properties info) {

if (stmtHandler == null) {
throw new IllegalArgumentException("Statement handler");
} // end of if

return connection(new ConnectionHandler.Default(handler), info);
if (resHandler == null) {
throw new IllegalArgumentException("Resource handler");
} // end of if

return connection(new ConnectionHandler.
Default(stmtHandler, resHandler), info);

} // end of connection

/**
@@ -0,0 +1,48 @@
package acolyte.jdbc;

import java.sql.SQLException;

/**
* Resource handler: allow to intercept management operations
* about the connection resources.
*/
public interface ResourceHandler {
/**
* Is fired when the transaction of |connection| is commited
* (but not for implicit commit in case of auto-commit).
*
* @see java.sql.Connection#commit
*/
public void whenCommitTransaction(Connection connection)
throws SQLException;

/**
* Is fired when the transaction of |connection| is rollbacked.
*
* @see java.sql.Connection#rollback
*/
public void whenRollbackTransaction(Connection connection)
throws SQLException;

// --- Inner classes ---

/**
* Default implementation.
*/
public static final class Default implements ResourceHandler {
public Default() {
}

/**
* {@inheritDoc}
*/
public void whenCommitTransaction(Connection connection)
throws SQLException {}

/**
* {@inheritDoc}
*/
public void whenRollbackTransaction(Connection connection)
throws SQLException {}
}
}
@@ -8,8 +8,27 @@ object ConnectionHandlerSpec extends Specification {
"Default handler" should {
"refuse null statement handler" in {
new ConnectionHandler.Default(null).
aka("ctor") must throwA[IllegalArgumentException]("Statement handler")

}

"refuse null resource handler" in {
new ConnectionHandler.Default(null, null).
aka("ctor") must throwA[IllegalArgumentException]

}

"update the resource handler" in {
val conHandler1 = new ConnectionHandler.Default(
test.EmptyStatementHandler)

val resHandler2 = new ResourceHandler.Default()
val conHandler2 = conHandler1.withResourceHandler(resHandler2)

conHandler1.hashCode must not(beEqualTo(conHandler2.hashCode)) and {
conHandler2.getResourceHandler.hashCode must not(beEqualTo(
conHandler1.getResourceHandler.hashCode))
}
}
}
}
@@ -287,6 +287,51 @@ object ConnectionSpec extends Specification with ConnectionFixtures {

}

"be intercepted" >> {
"successfully" in {
@volatile var rollback = 0

val conHandler = new ConnectionHandler {
def getStatementHandler = test.EmptyStatementHandler

def getResourceHandler = new ResourceHandler {
def whenCommitTransaction(c: Connection): Unit = ()

def whenRollbackTransaction(c: Connection): Unit = {
rollback += 1
}
}

def withResourceHandler(h: ResourceHandler): ConnectionHandler =
new ConnectionHandler.Default(test.EmptyStatementHandler, h)
}

connection(jdbcUrl, emptyClientInfo, conHandler).
rollback() must not(throwA[SQLException]) and {
rollback must_=== 1
}
}

"with exception" in {
val conHandler = new ConnectionHandler {
def getStatementHandler = test.EmptyStatementHandler

def getResourceHandler = new ResourceHandler {
def whenCommitTransaction(c: Connection): Unit = ()

def whenRollbackTransaction(c: Connection): Unit =
throw new SQLException("Foo")
}

def withResourceHandler(h: ResourceHandler): ConnectionHandler =
new ConnectionHandler.Default(test.EmptyStatementHandler, h)
}

connection(jdbcUrl, emptyClientInfo, conHandler).
rollback() must throwA[SQLException]("Foo")
}
}

"not be applied on closed connection" in {
lazy val c = defaultCon
c.close()
@@ -409,6 +454,51 @@ object ConnectionSpec extends Specification with ConnectionFixtures {
message = "Auto-commit is enabled"))

}

"be intercepted" >> {
"successfully" in {
@volatile var commit = 0

val conHandler = new ConnectionHandler {
def getStatementHandler = test.EmptyStatementHandler

def getResourceHandler = new ResourceHandler {
def whenCommitTransaction(c: Connection): Unit = {
commit += 1
}

def whenRollbackTransaction(c: Connection): Unit = ()
}

def withResourceHandler(h: ResourceHandler): ConnectionHandler =
new ConnectionHandler.Default(test.EmptyStatementHandler, h)
}

connection(jdbcUrl, emptyClientInfo, conHandler).
commit() must not(throwA[SQLException]) and {
commit must_=== 1
}
}

"with exception" in {
val conHandler = new ConnectionHandler {
def getStatementHandler = test.EmptyStatementHandler

def getResourceHandler = new ResourceHandler {
def whenCommitTransaction(c: Connection): Unit =
throw new SQLException("Bar")

def whenRollbackTransaction(c: Connection): Unit = ()
}

def withResourceHandler(h: ResourceHandler): ConnectionHandler =
new ConnectionHandler.Default(test.EmptyStatementHandler, h)
}

connection(jdbcUrl, emptyClientInfo, conHandler).
commit() must throwA[SQLException]("Bar")
}
}
}

"Auto-commit mode" should {
@@ -808,5 +898,5 @@ sealed trait ConnectionFixtures {

def defaultCon = connection(jdbcUrl, null, defaultHandler)

def connection(url: String, props: java.util.Properties, handler: ConnectionHandler) = new acolyte.jdbc.Connection(url, props, handler)
def connection(url: String, props: java.util.Properties, handler: ConnectionHandler) = new Connection(url, props, handler)
}
@@ -9,6 +9,10 @@ package object test {

object EmptyConnectionHandler extends ConnectionHandler {
def getStatementHandler = EmptyStatementHandler
def getResourceHandler = new ResourceHandler.Default()

def withResourceHandler(h: ResourceHandler): ConnectionHandler =
new ConnectionHandler.Default(EmptyStatementHandler, h)
}

object EmptyStatementHandler extends StatementHandler {

0 comments on commit f18cf94

Please sign in to comment.
You can’t perform that action at this time.