Provides a Unit of Work annotation for a Jdbi backed Dropwizard service for wrapping resource methods in a transaction context
-
Dropwizard
provides a very slick@UnitOfWork
annotation that wraps a transaction context around resource methods annotated with this annotation. This is very useful for wrapping multiple calls in a single database transaction all of which will succeed or roll back atomically. -
However, this support is only available for
Hibernate
. For all the goodnessJdbi
brings, we had to bring the transactionality on our own. This module provides support forJdbiUnitOfWork
with aJdbi
backend
This project is available on Maven Central. To add it to your project you can add the following dependency to your
pom.xml
:
<dependency>
<groupId>com.github.isopropylcyanide</groupId>
<artifactId>dropwizard-jdbi-unitofwork</artifactId>
<version>1.2</version>
</dependency>
transactionality
across multiple datasources when called from a request threadtransactionality
across multiple datasources acrossmultiple threads
excluding
selectively, certain set of URI's from transaction contexts, such asELB
,Health Checks
etcHttp GET
methods are excluded from transaction by default.Http POST
methods are wrapped around in a transaction only when annotated with@JdbiUnitOfWork
-
Add the dependency to your
pom.xml
-
Construct a
JdbiUnitOfWorkProvider
from the DBI instance.JdbiUnitOfWorkProvider provider = JdbiUnitOfWorkProvider.withDefault(dbi); // most common or JdbiUnitOfWorkProvider provider = JdbiUnitOfWorkProvider.withLinked(dbi);
If you are using Guice, you can bind the instance
bind(JdbiUnitOfWorkProvider.class).toInstance(provider);
-
Provide the list of package where the SQL Objects / DAO (to be attached) are located. Classes with Jdbi annotations
@SqlQuery
or@SqlUpdate
or@SqlBatch
or@SqlCall
will be picked automatically.
Use
JdbiUnitOfWorkProvider
to generate the proxies. You can also register the classes one by one.// class level SampleDao dao = (SampleDao) provider.getWrappedInstanceForDaoClass(SampleDao.class); // use the proxies and pass it as they were normal instances resource = new SampleResource(dao); // package level List<String> daoPackages = Lists.newArrayList("<fq-package-name>", "fq-package-name-2", ...); Map<? extends Class, Object> proxies = unitOfWorkProvider.getWrappedInstanceForDaoPackage(daoPackages); // use the proxies and pass it as they were normal instances resource = ...new SampleResource((SampleDao)proxies.get(SampleDao.class))
- Finally, we need to register the event listener with the Jersey Environment using the constructed provider
In case you'd like to exclude certain URI paths from being monitored, you can pass them into exclude paths;
environment.jersey().register(new JdbiUnitOfWorkApplicationEventListener(provider, new HashSet<>()));;
Set<String> excludePaths = new HashSet<>(); environment.jersey().register(new JdbiUnitOfWorkApplicationEventListener(handleManager, excludePaths));
- Start annotating resource methods with
@JdbiUnitOfWork
and you're good to go.@POST @Path("/") @JdbiUnitOfWork public RequestResponse createRequest() { ..do stateful work (across multiple Dao's) return response }
- This library relies on
Jersey Monitoring Events
to bind request lifecycle with a transaction aspect - At the backend, all
Jdbi
objects such asDao
orSqlObjects
are proxied behind aJdbiHandleManager
JdbiHandleManager
contract specifies theget
andclear
of the actual handles to the calling thread.
Please file bug reports and feature requests in GitHub issues.
Copyright (c) 2020-2023 Aman Garg
This library is licensed under the Apache License, Version 2.0.
See http://www.apache.org/licenses/LICENSE-2.0.html or the LICENSE file in this repository for the full license text.