use of org.jdbi.v3.sqlobject.Handler in project jdbi by jdbi.
the class TestUseCustomHandlerFactory method setUp.
@Before
public void setUp() throws Exception {
Jdbi db = dbRule.getJdbi();
HandlerFactory defaultHandlerFactory = new HandlerFactory() {
@Override
public Optional<Handler> buildHandler(Class<?> sqlObjectType, Method method) {
return getImplementation(sqlObjectType, method).map(m -> (Handler) (target, args, handle) -> m.invoke(null, Stream.concat(Stream.of(target), Stream.of(args)).toArray()));
}
private Optional<Method> getImplementation(Class<?> type, Method method) {
return Stream.of(type.getClasses()).filter(c -> c.getSimpleName().equals("DefaultImpls")).flatMap(c -> Stream.of(c.getMethods()).filter(m -> m.getName().equals(method.getName()))).findAny();
}
};
db.configure(Handlers.class, c -> c.register(defaultHandlerFactory));
handle = db.open();
}
use of org.jdbi.v3.sqlobject.Handler in project jdbi by jdbi.
the class SqlObjectFactory method attach.
/**
* Create a sql object of the specified type bound to this handle. Any state changes to the handle, or the sql
* object, such as transaction status, closing it, etc, will apply to both the object and the handle.
*
* @param extensionType the type of sql object to create
* @param handle the Handle instance to attach ths sql object to
* @return the new sql object bound to this handle
*/
@Override
public <E> E attach(Class<E> extensionType, HandleSupplier handle) {
Map<Method, Handler> handlers = methodHandlersFor(extensionType, handle.getConfig(Handlers.class), handle.getConfig(HandlerDecorators.class));
ConfigRegistry instanceConfig = handle.getConfig().createCopy();
for (Class<?> iface : extensionType.getInterfaces()) {
forEachConfigurer(iface, (configurer, annotation) -> configurer.configureForType(instanceConfig, annotation, extensionType));
}
forEachConfigurer(extensionType, (configurer, annotation) -> configurer.configureForType(instanceConfig, annotation, extensionType));
InvocationHandler invocationHandler = createInvocationHandler(extensionType, instanceConfig, handlers, handle);
return extensionType.cast(Proxy.newProxyInstance(extensionType.getClassLoader(), new Class[] { extensionType }, invocationHandler));
}
use of org.jdbi.v3.sqlobject.Handler in project jdbi by jdbi.
the class OnDemandExtensions method create.
static <E> E create(Jdbi db, Class<E> extensionType) {
ThreadLocal<E> threadExtension = new ThreadLocal<>();
InvocationHandler handler = (proxy, method, args) -> {
if (EQUALS_METHOD.equals(method)) {
return proxy == args[0];
}
if (HASHCODE_METHOD.equals(method)) {
return System.identityHashCode(proxy);
}
if (TOSTRING_METHOD.equals(method)) {
return extensionType + "@" + Integer.toHexString(System.identityHashCode(proxy));
}
if (threadExtension.get() != null) {
return invoke(threadExtension.get(), method, args);
}
return db.withExtension(extensionType, extension -> JdbiThreadLocals.invokeInContext(threadExtension, extension, () -> invoke(extension, method, args)));
};
return extensionType.cast(Proxy.newProxyInstance(extensionType.getClassLoader(), new Class[] { extensionType }, handler));
}
use of org.jdbi.v3.sqlobject.Handler in project jdbi by jdbi.
the class SqlObjectFactory method methodHandlersFor.
private Map<Method, Handler> methodHandlersFor(Class<?> sqlObjectType, Handlers registry, HandlerDecorators decorators) {
return handlersCache.computeIfAbsent(sqlObjectType, type -> {
final Map<Method, Handler> handlers = new HashMap<>();
handlers.putAll(handlerEntry((t, a, h) -> sqlObjectType.getName() + '@' + Integer.toHexString(t.hashCode()), Object.class, "toString"));
handlers.putAll(handlerEntry((t, a, h) -> t == a[0], Object.class, "equals", Object.class));
handlers.putAll(handlerEntry((t, a, h) -> System.identityHashCode(t), Object.class, "hashCode"));
handlers.putAll(handlerEntry((t, a, h) -> h.getHandle(), SqlObject.class, "getHandle"));
try {
handlers.putAll(handlerEntry((t, a, h) -> null, sqlObjectType, "finalize"));
}// optional implementation
catch (IllegalStateException expected) {
}
for (Method method : sqlObjectType.getMethods()) {
handlers.computeIfAbsent(method, m -> buildMethodHandler(sqlObjectType, m, registry, decorators));
}
return handlers;
});
}
use of org.jdbi.v3.sqlobject.Handler in project jdbi by jdbi.
the class TransactionDecorator method decorateHandler.
@Override
public Handler decorateHandler(Handler base, Class<?> sqlObjectType, Method method) {
final Transaction txnAnnotation = method.getAnnotation(Transaction.class);
final TransactionIsolationLevel isolation = txnAnnotation.value();
final boolean readOnly = txnAnnotation.readOnly();
return (target, args, handle) -> {
Handle h = handle.getHandle();
if (h.isInTransaction()) {
// Already in transaction. The outermost @Transaction method determines the transaction isolation level.
TransactionIsolationLevel currentLevel = h.getTransactionIsolationLevel();
if (currentLevel != isolation && isolation != TransactionIsolationLevel.UNKNOWN) {
throw new TransactionException("Tried to execute nested @Transaction(" + isolation + "), " + "but already running in a transaction with isolation level " + currentLevel + ".");
}
if (h.isReadOnly() && !readOnly) {
throw new TransactionException("Tried to execute a nested @Transaction(readOnly=false) " + "inside a readOnly transaction");
}
return base.invoke(target, args, handle);
}
HandleCallback<Object, Exception> callback = th -> base.invoke(target, args, handle);
final boolean flipReadOnly = readOnly != h.isReadOnly();
if (flipReadOnly) {
h.setReadOnly(readOnly);
}
try {
if (isolation == TransactionIsolationLevel.UNKNOWN) {
return h.inTransaction(callback);
} else {
return h.inTransaction(isolation, callback);
}
} finally {
if (flipReadOnly) {
h.setReadOnly(!readOnly);
}
}
};
}
Aggregations