public void testTransferNonHttpRequest_concurrentUseSameThreadOk() throws Exception { Callable<Boolean> callable = new Callable<Boolean>() { @Override public Boolean call() throws Exception { return ServletScopes.transferRequest(FALSE_CALLABLE).call(); } }; ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.of(); assertFalse(ServletScopes.scopeRequest(callable, seedMap).call()); }
return wrap(callable, continueRequest(seedMap));
@Override public Callable<Boolean> call() { final Object original = injector.getInstance(Object.class); return ServletScopes.transferRequest( new Callable<Boolean>() { @Override public Boolean call() { return original == injector.getInstance(Object.class); } }); } };
/** * Scopes the given callable inside a request scope. This is not the same as the HTTP request * scope, but is used if no HTTP request scope is in progress. In this way, keys can be scoped * as @RequestScoped and exist in non-HTTP requests (for example: RPC requests) as well as in HTTP * request threads. * * <p>The returned callable will throw a {@link ScopingException} when called if there is a * request scope already active on the current thread. * * @param callable code to be executed which depends on the request scope. Typically in another * thread, but not necessarily so. * @param seedMap the initial set of scoped instances for Guice to seed the request scope with. To * seed a key with null, use {@code null} as the value. * @return a callable that when called will run inside the a request scope that exposes the * instances in the {@code seedMap} as scoped keys. * @since 3.0 */ public static <T> Callable<T> scopeRequest(Callable<T> callable, Map<Key<?>, Object> seedMap) { return wrap(callable, scopeRequest(seedMap)); }
/** * Wraps the given callable in a contextual callable that "transfers" the request to another * thread. This acts as a way of transporting request context data from the current thread to a * future thread. * * <p>As opposed to {@link #continueRequest}, this method propagates all existing scoped objects. * The primary use case is in server implementations where you can detach the request processing * thread while waiting for data, and reattach to a different thread to finish processing at a * later time. * * <p>Because request-scoped objects are not typically thread-safe, the callable returned by this * method must not be run on a different thread until the current request scope has terminated. * The returned callable will block until the current thread has released the request scope. * * @param callable code to be executed in another thread, which depends on the request scope. * @return a callable that will invoke the given callable, making the request context available to * it. * @throws OutOfScopeException if this method is called from a non-request thread, or if the * request has completed. * @since 4.0 */ public static <T> Callable<T> transferRequest(Callable<T> callable) { return wrap(callable, transferRequest()); }
/** * Returns an object that "transfers" the request to another thread. This acts as a way of * transporting request context data from the current thread to a future thread. The transferred * scope is the one active for the thread that calls this method. A later call to {@code open()} * activates the transferred the scope, including propagating any objects scoped at that time. * * <p>As opposed to {@link #continueRequest}, this method propagates all existing scoped objects. * The primary use case is in server implementations where you can detach the request processing * thread while waiting for data, and reattach to a different thread to finish processing at a * later time. * * <p>Because request-scoped objects are not typically thread-safe, it is important to avoid * applying the same request scope concurrently. The returned Scoper will block on open until the * current thread has released the request scope. * * @return an object that when opened will initiate the request scope * @throws OutOfScopeException if this method is called from a non-request thread, or if the * request has completed. * @since 4.1 */ public static RequestScoper transferRequest() { return (GuiceFilter.localContext.get() != null) ? transferHttpRequest() : transferNonHttpRequest(); }
private static RequestScoper continueRequest(Map<Key<?>, Object> seedMap) { Preconditions.checkArgument( null != seedMap, "Seed map cannot be null, try passing in Collections.emptyMap() instead."); // Snapshot the seed map and add all the instances to our continuing HTTP request. final ContinuingHttpServletRequest continuingRequest = new ContinuingHttpServletRequest(GuiceFilter.getRequest(Key.get(HttpServletRequest.class))); for (Map.Entry<Key<?>, Object> entry : seedMap.entrySet()) { Object value = validateAndCanonicalizeValue(entry.getKey(), entry.getValue()); continuingRequest.setAttribute(entry.getKey().toString(), value); } return new RequestScoper() { @Override public CloseableScope open() { checkScopingState( null == GuiceFilter.localContext.get(), "Cannot continue request in the same thread as a HTTP request!"); return new GuiceFilter.Context(continuingRequest, continuingRequest, null).open(); } }; }
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { assertNull(someObject); // Seed with someobject. someObject = new SomeObject(); Callable<String> task = ServletScopes.continueRequest( callable, ImmutableMap.<Key<?>, Object>of(Key.get(SomeObject.class), someObject)); executorService.submit(task); } }
/** * Scopes the given callable inside a request scope. This is not the same as the HTTP request * scope, but is used if no HTTP request scope is in progress. In this way, keys can be scoped * as @RequestScoped and exist in non-HTTP requests (for example: RPC requests) as well as in HTTP * request threads. * * <p>The returned callable will throw a {@link ScopingException} when called if there is a * request scope already active on the current thread. * * @param callable code to be executed which depends on the request scope. Typically in another * thread, but not necessarily so. * @param seedMap the initial set of scoped instances for Guice to seed the request scope with. To * seed a key with null, use {@code null} as the value. * @return a callable that when called will run inside the a request scope that exposes the * instances in the {@code seedMap} as scoped keys. * @since 3.0 */ public static <T> Callable<T> scopeRequest(Callable<T> callable, Map<Key<?>, Object> seedMap) { return wrap(callable, scopeRequest(seedMap)); }
/** * Wraps the given callable in a contextual callable that "transfers" the request to another * thread. This acts as a way of transporting request context data from the current thread to a * future thread. * * <p>As opposed to {@link #continueRequest}, this method propagates all existing scoped objects. * The primary use case is in server implementations where you can detach the request processing * thread while waiting for data, and reattach to a different thread to finish processing at a * later time. * * <p>Because request-scoped objects are not typically thread-safe, the callable returned by this * method must not be run on a different thread until the current request scope has terminated. * The returned callable will block until the current thread has released the request scope. * * @param callable code to be executed in another thread, which depends on the request scope. * @return a callable that will invoke the given callable, making the request context available to * it. * @throws OutOfScopeException if this method is called from a non-request thread, or if the * request has completed. * @since 4.0 */ public static <T> Callable<T> transferRequest(Callable<T> callable) { return wrap(callable, transferRequest()); }
Object value = validateAndCanonicalizeValue(entry.getKey(), entry.getValue()); scopeMap.put(entry.getKey().toString(), value);
/** * Returns an object that "transfers" the request to another thread. This acts as a way of * transporting request context data from the current thread to a future thread. The transferred * scope is the one active for the thread that calls this method. A later call to {@code open()} * activates the transferred the scope, including propagating any objects scoped at that time. * * <p>As opposed to {@link #continueRequest}, this method propagates all existing scoped objects. * The primary use case is in server implementations where you can detach the request processing * thread while waiting for data, and reattach to a different thread to finish processing at a * later time. * * <p>Because request-scoped objects are not typically thread-safe, it is important to avoid * applying the same request scope concurrently. The returned Scoper will block on open until the * current thread has released the request scope. * * @return an object that when opened will initiate the request scope * @throws OutOfScopeException if this method is called from a non-request thread, or if the * request has completed. * @since 4.1 */ public static RequestScoper transferRequest() { return (GuiceFilter.localContext.get() != null) ? transferHttpRequest() : transferNonHttpRequest(); }
public ExtDirectJsonRequestProcessorThread() { Subject subject = SecurityUtils.getSubject(); checkState(subject != null, "Subject is not set"); // create the thread state by this moment as this is created in the master (web container) thread threadState = new SubjectThreadState(subject); processRequest = ServletScopes.continueRequest(new Callable<String>() { @Override public String call() { threadState.bind(); UserIdMdcHelper.set(); try { return ExtDirectJsonRequestProcessorThread.super.processRequest(); } finally { UserIdMdcHelper.unset(); threadState.restore(); } } }, Collections.<Key<?>, Object>emptyMap()); }
public void testTransferNonHttpRequest_concurrentUseSameThreadOk_closeable() throws Exception { Callable<Boolean> callable = new Callable<Boolean>() { @Override public Boolean call() throws Exception { RequestScoper.CloseableScope scope = ServletScopes.transferRequest().open(); try { return false; } finally { scope.close(); } } }; ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.of(); assertFalse(ServletScopes.scopeRequest(callable, seedMap).call()); } }
@Override public Data call() { Data data = new Data(); data.object = injector.getInstance(Object.class); data.scoper = ServletScopes.transferRequest(); return data; } };
/** * Scopes the given callable inside a request scope. This is not the same as the HTTP request * scope, but is used if no HTTP request scope is in progress. In this way, keys can be scoped * as @RequestScoped and exist in non-HTTP requests (for example: RPC requests) as well as in HTTP * request threads. * * <p>The returned callable will throw a {@link ScopingException} when called if there is a * request scope already active on the current thread. * * @param callable code to be executed which depends on the request scope. Typically in another * thread, but not necessarily so. * @param seedMap the initial set of scoped instances for Guice to seed the request scope with. To * seed a key with null, use {@code null} as the value. * @return a callable that when called will run inside the a request scope that exposes the * instances in the {@code seedMap} as scoped keys. * @since 3.0 */ public static <T> Callable<T> scopeRequest(Callable<T> callable, Map<Key<?>, Object> seedMap) { return wrap(callable, scopeRequest(seedMap)); }
/** * Wraps the given callable in a contextual callable that "transfers" the request to another * thread. This acts as a way of transporting request context data from the current thread to a * future thread. * * <p>As opposed to {@link #continueRequest}, this method propagates all existing scoped objects. * The primary use case is in server implementations where you can detach the request processing * thread while waiting for data, and reattach to a different thread to finish processing at a * later time. * * <p>Because request-scoped objects are not typically thread-safe, the callable returned by this * method must not be run on a different thread until the current request scope has terminated. * The returned callable will block until the current thread has released the request scope. * * @param callable code to be executed in another thread, which depends on the request scope. * @return a callable that will invoke the given callable, making the request context available to * it. * @throws OutOfScopeException if this method is called from a non-request thread, or if the * request has completed. * @since 4.0 */ public static <T> Callable<T> transferRequest(Callable<T> callable) { return wrap(callable, transferRequest()); }
return wrap(callable, continueRequest(seedMap));
Object value = validateAndCanonicalizeValue(entry.getKey(), entry.getValue()); scopeMap.put(entry.getKey().toString(), value);
/** * Returns an object that "transfers" the request to another thread. This acts as a way of * transporting request context data from the current thread to a future thread. The transferred * scope is the one active for the thread that calls this method. A later call to {@code open()} * activates the transferred the scope, including propagating any objects scoped at that time. * * <p>As opposed to {@link #continueRequest}, this method propagates all existing scoped objects. * The primary use case is in server implementations where you can detach the request processing * thread while waiting for data, and reattach to a different thread to finish processing at a * later time. * * <p>Because request-scoped objects are not typically thread-safe, it is important to avoid * applying the same request scope concurrently. The returned Scoper will block on open until the * current thread has released the request scope. * * @return an object that when opened will initiate the request scope * @throws OutOfScopeException if this method is called from a non-request thread, or if the * request has completed. * @since 4.1 */ public static RequestScoper transferRequest() { return (GuiceFilter.localContext.get() != null) ? transferHttpRequest() : transferNonHttpRequest(); }