All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.jersey.process.internal.RequestScope Maven / Gradle / Ivy

Go to download

A bundle project producing JAX-RS RI bundles. The primary artifact is an "all-in-one" OSGi-fied JAX-RS RI bundle (jaxrs-ri.jar). Attached to that are two compressed JAX-RS RI archives. The first archive (jaxrs-ri.zip) consists of binary RI bits and contains the API jar (under "api" directory), RI libraries (under "lib" directory) as well as all external RI dependencies (under "ext" directory). The secondary archive (jaxrs-ri-src.zip) contains buildable JAX-RS RI source bundle and contains the API jar (under "api" directory), RI sources (under "src" directory) as well as all external RI dependencies (under "ext" directory). The second archive also contains "build.xml" ANT script that builds the RI sources. To build the JAX-RS RI simply unzip the archive, cd to the created jaxrs-ri directory and invoke "ant" from the command line.

There is a newer version: 3.1.9
Show newest version
/*
 * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.process.internal;

import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.glassfish.jersey.internal.BootstrapBag;
import org.glassfish.jersey.internal.BootstrapConfigurator;
import org.glassfish.jersey.internal.Errors;
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.internal.util.ExtendedLogger;
import org.glassfish.jersey.internal.util.Producer;

import static org.glassfish.jersey.internal.guava.Preconditions.checkState;

/**
 * Scopes a single request/response processing execution on a single thread.
 * 

* To execute a code inside of the request scope use one of the {@code runInScope(...)} * methods and supply the task encapsulating the code that should be executed in the scope. *

*

* Example: *

*
 * @Inject
 * RequestScope requestScope;
 *
 * ...
 *
 * requestScope.runInScope(new Runnable() {
 *     @Override
 *     public void run() {
 *          System.out.println("This is executed in the request scope...");
 *     }
 * });
 * 
*

* An instance of the request scope can be suspended and retrieved via a call to * {@link RequestScope#suspendCurrent} method. This instance can be later * used to resume the same request scope and run another task in the same scope: *

*
 *  RequestContext requestScopeContext =
 *      requestScope.runInScope(new Callable<Instance>() {
 *          @Override
 *          public RequestContext call() {
 *              // This is executed in the new request scope.
 *
 *              // The following call will cause that the
 *              // RequestContext will not be released
 *              // automatically and we will have to release
 *              // it explicitly at the end.
 *              return requestScope.suspendCurrent();
 *          }
 *      });
 *
 *  requestScope.runInScope(requestScopeContext, new Runnable() {
 *
 *      @Override
 *      public void run() {
 *          // This is executed in the same request scope as code above.
 *      }
 *  });
 *
 *  // The scope context must be explicitly released.
 *  requestScopeContext.release();
 * 
*

* In the previous example the {@link RequestContext request scope context} * was suspended and retrieved which also informs {@code requestScope} that it * should not automatically release the instance once the running task is finished. * The {@code requestScopeContext} is then used to initialize the next * request-scoped execution. The second task will run in the same request scope as the * first task. At the end the suspended {@code requestScopeContext} must be * manually {@link RequestContext#release released}. Not releasing the instance * could cause memory leaks. Please note that calling {@link RequestScope#suspendCurrent} * does not retrieve an immutable snapshot of the current request scope but * a live reference to the internal {@link RequestContext request scope context} * which may change it's state during each request-scoped task execution for * which this scope context is used. *

* * @author Marek Potociar * @author Miroslav Fuksa */ public abstract class RequestScope { private static final ExtendedLogger logger = new ExtendedLogger(Logger.getLogger(RequestScope.class.getName()), Level.FINEST); /** * A thread local copy of the current scope context. */ private final ThreadLocal currentRequestContext = new ThreadLocal<>(); private volatile boolean isActive = true; public boolean isActive() { return isActive; } public void shutdown() { isActive = false; } /** * Get a new reference for to currently running request scope context. This call * prevents automatic {@link RequestContext#release() release} of the scope * context once the task that runs in the scope has finished. *

* The returned scope context may be used to run additional task(s) in the * same request scope using one of the {@code #runInScope(RequestContext, ...)} methods. *

*

* Note that the returned context must be {@link RequestContext#release() * released} manually once not needed anymore to prevent memory leaks. *

* * @return currently active {@link RequestContext request scope context}. * @throws IllegalStateException in case there is no active request scope associated * with the current thread or if the request scope has * been already shut down. * @see #suspendCurrent() */ public RequestContext referenceCurrent() throws IllegalStateException { return current().getReference(); } /** * Returns the current {@link RequestContext} which has to be active on the given thread. * * @return current active request context. */ public RequestContext current() { checkState(isActive, "Request scope has been already shut down."); final RequestContext scopeInstance = currentRequestContext.get(); checkState(scopeInstance != null, "Not inside a request scope."); return scopeInstance; } private RequestContext retrieveCurrent() { checkState(isActive, "Request scope has been already shut down."); return currentRequestContext.get(); } /** * Get the current {@link RequestContext request scope context} * and mark it as suspended. This call prevents automatic * {@link RequestContext#release() release} of the scope context * once the task that runs in the scope has finished. *

* The returned scope context may be used to run additional task(s) in the * same request scope using one of the {@code #runInScope(RequestContext, ...)} * methods. *

*

* Note that the returned context must be {@link RequestContext#release() * released} manually once not needed anymore to prevent memory leaks. *

* * @return currently active {@link RequestContext request scope context} * that was suspended or {@code null} if the thread is not currently running * in an active request scope. * @see #referenceCurrent() */ public RequestContext suspendCurrent() { final RequestContext context = retrieveCurrent(); if (context == null) { return null; } try { RequestContext referencedContext = context.getReference(); suspend(referencedContext); return referencedContext; } finally { logger.debugLog("Returned a new reference of the request scope context {0}", context); } } /** * Executes the action when the request scope comes into suspended state. For example, implementation can call deactivation * of the underlying request scope storage. * * @param context current request context to be suspended. */ protected void suspend(RequestContext context) { } /** * Creates a new instance of the {@link RequestContext request scope context}. * This instance can be then used to run task in the request scope. Returned context * is suspended by default and must therefore be closed explicitly as it is shown in * the following example: *
     * RequestContext context = requestScope.createContext();
     * requestScope.runInScope(context, someRunnableTask);
     * context.release();
     * 
* * @return New suspended request scope context. */ public abstract RequestContext createContext(); /** * Stores the provided {@link RequestContext} to thread-local variable belonging to current request scope. * * @param context storage with request scoped objects. */ protected void activate(RequestContext context, RequestContext oldContext) { checkState(isActive, "Request scope has been already shut down."); currentRequestContext.set(context); } /** * Resumes the provided {@link RequestContext} to thread-local variable belonging to current request scope. * * @param context storage with request scoped objects. */ protected void resume(RequestContext context) { currentRequestContext.set(context); } /** * Releases the provided {@link RequestContext} to thread-local variable belonging to current request scope. * * @param context storage with request scoped objects. */ protected void release(RequestContext context) { context.release(); currentRequestContext.remove(); } /** * Runs the {@link Runnable task} in the request scope initialized from the * {@link RequestContext scope context}. The {@link RequestContext * scope context} is NOT released by the method (this must be done explicitly). The * current thread might be already in any request scope and in that case the scope * will be changed to the scope defined by the {@link RequestContext scope * instance}. At the end of the method the request scope is returned to its original * state. * * @param context The request scope context from which the request scope will be initialized. * @param task Task to be executed. */ public void runInScope(RequestContext context, Runnable task) { final RequestContext oldContext = retrieveCurrent(); try { activate(context.getReference(), oldContext); Errors.process(task); } finally { release(context); resume(oldContext); } } /** * Runs the {@link Runnable task} in the new request scope. The current thread might * be already in any request scope and in that case the scope will be changed to the * scope defined by the {@link RequestContext scope context}. At the end of * the method the request scope is returned to its original state. The newly created * {@link RequestContext scope context} will be implicitly released at the end * of the method call except the task will call * {@link RequestScope#suspendCurrent}. * * @param task Task to be executed. */ public void runInScope(Runnable task) { final RequestContext oldContext = retrieveCurrent(); final RequestContext context = createContext(); try { activate(context, oldContext); Errors.process(task); } finally { release(context); resume(oldContext); } } /** * Runs the {@link Callable task} in the request scope initialized from the * {@link RequestContext scope context}. The {@link RequestContext * scope context} is NOT released by the method (this must be done explicitly). The * current thread might be already in any request scope and in that case the scope * will be changed to the scope defined by the {@link RequestContext scope * instance}. At the end of the method the request scope is returned to its original * state. * * @param context The request scope context from which the request scope will be initialized. * @param task Task to be executed. * @param {@code task} result type. * @return result returned by the {@code task}. * @throws Exception Exception thrown by the {@code task}. */ public T runInScope(RequestContext context, Callable task) throws Exception { final RequestContext oldContext = retrieveCurrent(); try { activate(context.getReference(), oldContext); return Errors.process(task); } finally { release(context); resume(oldContext); } } /** * Runs the {@link Callable task} in the new request scope. The current thread might * be already in any request scope and in that case the scope will be changed to the * scope defined by the {@link RequestContext scope context}. At the end of * the method the request scope is returned to its original state. The newly created * {@link RequestContext scope context} will be implicitly released at the end * of the method call except the task will call * {@link RequestScope#suspendCurrent}. * * @param task Task to be executed. * @param {@code task} result type. * @return result returned by the {@code task}. * @throws Exception Exception thrown by the {@code task}. */ public T runInScope(Callable task) throws Exception { final RequestContext oldContext = retrieveCurrent(); final RequestContext context = createContext(); try { activate(context, oldContext); return Errors.process(task); } finally { release(context); resume(oldContext); } } /** * Runs the {@link org.glassfish.jersey.internal.util.Producer task} in the request scope initialized * from the {@link RequestContext scope context}. * The {@link RequestContext scope context} is NOT released by the method (this * must be done explicitly). The current thread might be already in any request scope * and in that case the scope will be changed to the scope defined by the * {@link RequestContext scope context}. At the end of the method the request * scope is returned to its original state. * * @param context The request scope context from which the request scope will be initialized. * @param task Task to be executed. * @param {@code task} result type. * @return result returned by the {@code task} */ public T runInScope(RequestContext context, Producer task) { final RequestContext oldContext = retrieveCurrent(); try { activate(context.getReference(), oldContext); return Errors.process(task); } finally { release(context); resume(oldContext); } } /** * Runs the {@link org.glassfish.jersey.internal.util.Producer task} in the new request scope. The * current thread might be already in any request scope and in that case the scope * will be changed to the scope defined by the {@link RequestContext scope * instance}. At the end of the method the request scope is returned to its original * state. The newly created {@link RequestContext scope context} will be * implicitly released at the end of the method call except the task will call * {@link RequestScope#suspendCurrent}. * * @param task Task to be executed. * @param {@code task} result type. * @return result returned by the {@code task}. */ public T runInScope(Producer task) { final RequestContext oldContext = retrieveCurrent(); final RequestContext context = createContext(); try { activate(context, oldContext); return Errors.process(task); } finally { release(context); resume(oldContext); } } /** * Configurator which initializes and register {@link RequestScope} instance int {@link InjectionManager} and * {@link BootstrapBag}. * * @author Petr Bouda */ public static class RequestScopeConfigurator implements BootstrapConfigurator { @Override public void init(InjectionManager injectionManagerFactory, BootstrapBag bootstrapBag) { } @Override public void postInit(InjectionManager injectionManager, BootstrapBag bootstrapBag) { RequestScope requestScope = injectionManager.getInstance(RequestScope.class); bootstrapBag.setRequestScope(requestScope); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy