Last active
May 18, 2018 13:43
-
-
Save mnadel/10224102 to your computer and use it in GitHub Desktop.
Dropwizard + Hystrix + Hibernate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.apache.commons.lang3.Validate; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import java.util.concurrent.Callable; | |
/** | |
* A database session and transaction-aware Callable | |
*/ | |
class DatabaseCallable<T> implements Callable<T> | |
{ | |
private static final Logger log = LoggerFactory.getLogger(DatabaseCallable.class); | |
private final Callable<T> underlying; | |
private final DatabaseContext ctx; | |
DatabaseCallable(final Runnable underlying, DatabaseContext ctx) { | |
this(new Callable<T>() { | |
@Override | |
public T call() throws Exception { | |
underlying.run(); | |
return null; | |
} | |
}, ctx); | |
} | |
DatabaseCallable(Callable<T> underlying, DatabaseContext ctx) { | |
Validate.notNull(underlying); | |
Validate.notNull(ctx); | |
this.underlying = underlying; | |
this.ctx = ctx; | |
} | |
/** | |
* Invoke the underlying callable within the context of a Session and, if requested, | |
* within the context of a Transaction. | |
*/ | |
@Override | |
public T call() throws Exception { | |
try { | |
ctx.bind(); | |
ctx.beginIfNeeded(); | |
T result = underlying.call(); | |
ctx.commitIfNeeded(); | |
return result; | |
} catch (Exception e) { | |
ctx.rollbackIfNeeded(); | |
log.error("Error executing database work", e); | |
throw e; | |
} finally { | |
ctx.unbind(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.apache.commons.lang3.Validate; | |
import org.hibernate.*; | |
import org.hibernate.context.internal.ManagedSessionContext; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
class DatabaseContext | |
{ | |
private static final Logger log = LoggerFactory.getLogger(DatabaseContext.class); | |
private Session session; | |
private Transaction transaction; | |
private final SessionFactory sessionFactory; | |
private final boolean needsTransaction; | |
DatabaseContext(SessionFactory sessionFactory, boolean needsTransaction) { | |
Validate.notNull(sessionFactory); | |
this.sessionFactory = sessionFactory; | |
this.needsTransaction = needsTransaction; | |
} | |
Session bind() { | |
if (log.isDebugEnabled()) { | |
log.debug("Opening session"); | |
} | |
session = sessionFactory.openSession(); | |
ManagedSessionContext.bind(session); | |
return session; | |
} | |
void unbind() { | |
try { | |
if (activeTransaction()) { | |
if (log.isDebugEnabled()) { | |
log.error("Rolling back abandoned transaction"); | |
} | |
transaction.rollback(); | |
} | |
if (log.isDebugEnabled()) { | |
log.debug("Unbinding session"); | |
} | |
} catch (Exception e) { | |
log.error("Cannot roll back abandoned transaction", e); | |
} finally { | |
try { | |
session.close(); | |
} catch (Exception e) { | |
log.error("Error closing session", e); | |
} | |
ManagedSessionContext.unbind(sessionFactory); | |
} | |
} | |
void beginIfNeeded() { | |
if (needsTransaction) { | |
if (log.isDebugEnabled()) { | |
log.debug("Starting transaction"); | |
} | |
transaction = session.beginTransaction(); | |
} | |
} | |
void commitIfNeeded() { | |
if (pendingTransaction()) { | |
if (log.isDebugEnabled()) { | |
log.debug("Committing transaction"); | |
} | |
transaction.commit(); | |
} | |
} | |
void rollbackIfNeeded() { | |
if (pendingTransaction()) { | |
if (log.isDebugEnabled()) { | |
log.debug("Rolling back transaction"); | |
} | |
transaction.rollback(); | |
} | |
} | |
private boolean pendingTransaction() { | |
return null != transaction; | |
} | |
private boolean activeTransaction() { | |
return pendingTransaction() && transaction.isActive(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.netflix.hystrix.HystrixCommand; | |
import java.util.concurrent.Callable; | |
public abstract class HystrixCommandBuilder<T> | |
{ | |
protected abstract Setter createSetter(); | |
public HystrixCommand<T> build(Callable<T> action, DatabaseContext dbCtx) { | |
final Callable<T> actionDelegate = null != dbCtx | |
? new DatabaseCallable<T>(callable, dbCtx) | |
: callable; | |
return new HystrixCommand<T>(createSetter()) { | |
@Override | |
protected T run() throws Exception { | |
return actionDelegate.call(); | |
} | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment