pl.morgwai.base.guice.scopes.ServerSideContext Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of guice-context-scopes Show documentation
Show all versions of guice-context-scopes Show documentation
Classes for building Guice scopes, that get automatically transferred when dispatching work to other threads
// Copyright (c) Piotr Morgwai Kotarbinski, Licensed under the Apache License, Version 2.0
package pl.morgwai.base.guice.scopes;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.google.inject.Key;
import com.google.inject.Provider;
/**
* Stores attributes associated with some server-side processing/call (such as a servlet request
* processing, an RPC or a session combining several received calls) and allows to execute
* operations within itself.
*
* Overriding classes must use themselves as {@code CtxT} type argument.
*
* Overriding classes usually add properties and methods specific to a given type of call, like
* given call's arguments etc.
*
* If multiple threads run within the same context, the attributes that they access must be
* thread-safe or properly synchronized.
*/
public abstract class ServerSideContext> {
final ConcurrentMap, Object> attributes = new ConcurrentHashMap<>();
final ContextTracker tracker;
protected ServerSideContext(ContextTracker tracker) {
this.tracker = tracker;
}
/**
* Sets itself as the current context for the current thread and executes {@code operation}
* synchronously. Afterwards clears the current context.
*
* @see ContextTrackingExecutor#executeWithinAll(java.util.List, Runnable)
*/
@SuppressWarnings("unchecked")
public void executeWithinSelf(Runnable operation) {
tracker.trackWhileExecuting((CtxT) this, operation);
}
/**
* Sets itself as the current context for the current thread and executes {@code operation}
* synchronously. Afterwards clears the current context.
*
* @see ContextTrackingExecutor#executeWithinAll(java.util.List, Callable)
*/
@SuppressWarnings("unchecked")
public T executeWithinSelf(Callable operation) throws Exception {
return tracker.trackWhileExecuting((CtxT) this, operation);
}
/**
* Removes the attribute given by key
from this context. This is sometimes useful
* to force the associated {@link ContextScope} to obtain a new instance from the unscoped
* provider if the current one is not usable anymore (for example a timed-out connection, etc).
*
* Note: If multiple threads run within the same context, care must be taken to prevent
* some of them from retaining the old stale instance.
*/
public void removeAttribute(Key> key) {
attributes.remove(key);
}
/**
* Obtains the attribute given by {@code key}. If it is not yet present in this context,
* asks {@code provider} for a new instance and stores the result for subsequent calls.
* For internal use by {@link ContextScope#scope(Key, com.google.inject.Provider)}.
*/
@SuppressWarnings("unchecked")
T provideAttributeIfAbsent(Key key, Provider provider) {
return (T) attributes.computeIfAbsent(key, (ignored) -> provider.get());
}
}