Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JDBC transaction handlers #90

Merged
merged 4 commits into from
Sep 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions jdbc-driver/src/main/java/acolyte/jdbc/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -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

/**
Expand All @@ -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

/**
Expand Down
58 changes: 52 additions & 6 deletions jdbc-driver/src/main/java/acolyte/jdbc/ConnectionHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,56 @@ public interface ConnectionHandler {
*/
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>

/**
Expand All @@ -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
26 changes: 22 additions & 4 deletions jdbc-driver/src/main/java/acolyte/jdbc/Driver.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ public static acolyte.jdbc.Connection connection(final ConnectionHandler handler
* @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
Expand Down Expand Up @@ -211,12 +210,31 @@ public static acolyte.jdbc.Connection connection(StatementHandler handler) {
* @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

/**
Expand Down
48 changes: 48 additions & 0 deletions jdbc-driver/src/main/java/acolyte/jdbc/ResourceHandler.java
Original file line number Diff line number Diff line change
@@ -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 {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}
}
}
92 changes: 91 additions & 1 deletion jdbc-driver/src/test/scala/acolyte/jdbc/ConnectionSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}
4 changes: 4 additions & 0 deletions jdbc-driver/src/test/scala/acolyte/jdbc/test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading