I am in the process of developing a multi tenancy application with Jersey using Guice for DI (I also use Dropwizard but I don\'t think it matters here).
One thing
I finally figured it out by myself. The Guice page about custom scopes was a good starting point. I needed to tweak it a bit though.
First I've created a @TenancyScoped
annotation:
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@ScopeAnnotation
public @interface TenancyScoped { }
Then I used a request filter:
@PreMatching
public class TenancyScopeRequestFilter implements ContainerRequestFilter {
private final TenancyScope scope;
@Inject
public TenancyScopeRequestFilter(TenancyScope scope) {
this.scope = scope;
}
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
Optional tenancyId = getTenancyId(requestContext);
if (!tenancyId.isPresent()) {
scope.exit();
return;
}
scope.enter(tenancyId.get());
}
private Optional getTenancyId(ContainerRequestContext requestContext) {
}
}
Please note the @PreMatching
annotation. It is important that every request is filtered, otherwise your code might behave weirdly (scope could be set incorrectly).
And here comes the TenancyScope
implementation:
public class TenancyScope implements Scope, Provider {
private final Logger logger = LoggerFactory.getLogger(TenancyScope.class);
private final ThreadLocal
The last step is to wire everything together in the Guice module:
@Override
protected void configure() {
TenancyScope tenancyScope = new TenancyScope();
bindScope(TenancyScoped.class, tenancyScope);
bind(TenancyScope.class).toInstance(tenancyScope);
bind(TenancyId.class).toProvider(tenancyScope).in(TenancyScoped.class);
}
What you have now is a scope that is set before each request and all instances the are provided by Guice are cached per tenancy id (also per thread, but that can be changed easily). Basically you have a object graph per tenant id (similar to having one per session e.g.).
Also notice, that the TenancyScope
class acts both as a Scope
and a TenancyId
provider.