blob: df3dd918b46eb75f6d972ca375fd0117b0d44b19 [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package javax.portlet;
/**
* <div class="changed_added_3_0">
* Class representing the execution context for an asynchronous operation that was
* initiated on a ResourceRequest.
* <p>
* Portlet asynchronous support is modeled after servlet asynchronous support, and in
* general, the portlet async methods behave in the same manner as their
* <code>AsyncContext</code> analog.
* <p>
* A <code>PortletAsyncContext</code> is created and initialized by a call to
* <code>ResourceRequest#startAsync()</code> or
* <code>ResourceRequest#startAsync(ServletRequest, ServletResponse)</code>.
* Repeated invocations of these methods will return the same
* <code>PortletAsyncContext</code> instance, reinitialized as appropriate.
* <p>
* In the event that an asynchronous operation times out, the container will
* invoke the onTimeout method of all <code>PortletAsyncListener</code> instances registered
* with the <code>PortletAsyncContext</code> on which the asynchronous operation was initiated.
* If none of the listeners call <code>complete()</code> or any of the
* <code>dispatch()</code> methods, the portlet container will
* complete the request on behalf of the application and may respond with error information.
* </div>
*
* @see javax.servlet.AsyncContext
* @see PortletAsyncListener
* @see PortletAsyncEvent
*
* @since 3.0
*/
public interface PortletAsyncContext {
/**
* <div class="changed_added_3_0">
* Registers the given <code>PortletAsyncListener</code> with the most recent
* asynchronous cycle that was started by a call to one of the
* <code>ResourceRequest.startAsync()</code> methods.
* <p>
* The given <code>PortletAsyncListener</code> will receive an
* <code>PortletAsyncEvent</code> when the
* asynchronous cycle completes successfully, times out, results in an error, or a
* new asynchronous cycle is being initiated via one of the
* <code>ResourceRequest.startAsync()</code> methods.
* <p>
* <code>PortletAsyncListener</code> instances will be notified in the order in
* which they were added.
* <p>
* When one of the listener methods is invoked, the
* <code>PortletAsyncListener</code> <code>getSuppliedRequest()</code> and
* <code>getSuppliedResponse()</code> methods of the
* <code>PortletAsyncEvent</code> object will return <code>null</code>.
* </div>
*
* @see PortletAsyncListener
* @see PortletAsyncEvent
*
* @param listener the listener to be added
* @throws IllegalStateException
* if this method is called after the container-initiated dispatch, during which
* one of the <code>ResourceRequest.startAsync()</code> methods was called, has
* returned to the container
*
*/
public void addListener(PortletAsyncListener listener) throws IllegalStateException;
/**
* <div class="changed_added_3_0">
* Registers the given <code>PortletAsyncListener</code> with the most recent
* asynchronous cycle that was started by a call to one of the
* <code>ResourceRequest.startAsync()</code> methods.
* <p>
* The given <code>PortletAsyncListener</code> will receive an
* <code>PortletAsyncEvent</code> when the
* asynchronous cycle completes successfully, times out, results in an error, or a
* new asynchronous cycle is being initiated via one of the
* <code>ResourceRequest.startAsync()</code> methods.
* <p>
* <code>PortletAsyncListener</code> instances will be notified in the order in
* which they were added.
* <p>
* The given <code>ResourceRequest</code> and <code>ResourceResponse</code> objects will be made
* available to the given <code>PortletAsyncListener</code> via the
* <code>getSuppliedRequest</code> and
* <code>getSuppliedResponse</code> methods, respectively, of the
* <code>PortletAsyncEvent</code> delivered to
* it. These objects should not be read from or written to at the
* time the <code>PortletAsyncEvent</code> is delivered, because additional wrapping
* may have
* occurred since the given <code>PortletAsyncListener</code> was registered.
* However, they may be used to release any resources associated with them.
* </div>
*
* @see PortletAsyncListener
* @see PortletAsyncEvent
*
* @param listener the listener to be added
* @param request the request object to be included in the <code>PortletAsyncEvent</code>
* @param response the response object to be included in the <code>PortletAsyncEvent</code>
* @throws IllegalStateException
* if this method is called after the container-initiated dispatch, during which
* one of the <code>ResourceRequest.startAsync()</code> methods was called, has
* returned to the container
*
*/
public void addListener(PortletAsyncListener listener, ResourceRequest request, ResourceResponse response) throws IllegalStateException;
/**
* <div class="changed_added_3_0">
* Completes the <code>PortletAsynchronous</code> operation
* and closes the response associated with this <code>PortletAsyncContext</code> object.
* <p>
* The <code>onComplete</code> method of any registered listeners that were registered
* with the <code>PortletAsyncContext</code> object for this asynchronous cycle
* will be invoked.
* <p>
* It is legal to call this method any time after a call to
* <code>ResourceRequest#startAsync()</code> or
* <code>ResourceRequest#startAsync(ResourceRequest, ResourceResponse)</code>,
* and before a call to one of the dispatch methods of this
* class. If this method is called before the container-initiated dispatch that
* called <code>startAsync</code> has returned to the container, then the call will
* not take effect (and any invocations of
* <code>PortletAsyncListener#onComplete(PortletAsyncEvent)</code> will
* be delayed) until after the container-initiated dispatch has returned to the
* container.
* </div>
*
* @throws IllegalStateException
* if this method is called before an asynchronous processing cycle was started,
* after it has already been completed, or after a call to
* one of the <code>dispatch()</code> methods
*
*/
public void complete() throws IllegalStateException;
/**
* <div class="changed_added_3_0">
* Instantiates the given <code>PortletAsyncListener</code> class.
* <p>
* The returned <code>PortletAsyncListener</code> instance may be further customized before it is
* registered with this <code>PortletAsyncContext</code> via a call to one of the addListener methods.
* <p>
* The given <code>PortletAsyncListener</code> class must define a zero argument constructor, which is
* used to instantiate it.
* <p>
* This method supports resource injection if contextual support is available, and if
* the given class represents a Managed
* Bean. See the Java EE platform and JSR 299 specifications for additional details
* about Managed Beans and resource injection.
* </div>
*
* @param cls the class to be instantiated
* @return the instantiated class
* @throws PortletException if the given class cannot be instantiated
*/
public <T extends PortletAsyncListener> T createPortletAsyncListener(Class<T> cls) throws PortletException;
/**
* <div class="changed_added_3_0">
* Dispatches the request and response objects of this <code>PortletAsyncContext</code> to
* the portlet container.
* <p>
* The portlet container will dispatch the the request and response to the
* portlet resource method in which the first asynchronous processing cycle was
* initiated.
* <p>
* This method returns immediately after passing the request and response
* objects to a container managed thread which will perform the dispatch
* operation. If this method is called before the container-initiated dispatch
* that called startAsync has returned to the container, the dispatch operation
* will be delayed until after the container-initiated dispatch has returned to
* the container.
* <p>
* The dispatcher type of the request is set to <code>DispatcherType.ASYNC</code>. Unlike
* forward dispatches, the response buffer and headers will not be reset, and
* it is legal to dispatch even if the response has already been committed.
* <p>
* Control over the request and response is delegated to the dispatch target,
* and the response will be closed when the dispatch target has completed
* execution, unless <code>ResourceRequest#startAsync()</code> or
* <code>ResourceRequest#startAsync(ResourceRequest, ResourceResponse)</code> are called.
* <p>
* Any errors or exceptions that may occur during the execution of this method
* must be caught and handled by the container as follows:
* <ul>
* <li>
* Invoke the <code>onError</code> method of all <code>PortletAsyncListener</code>
* instances registered with this <code>PortletAsyncContext</code> and
* make the caught <code>Throwable</code> available via
* <code>PortletAsyncEvent#getThrowable</code>.
* </li>
* <li>
* If none of the listeners called <code>complete()</code> or any of the <code>dispatch()</code>
* methods, set the status code equal to
* <code>HttpResourceResponse.SC_INTERNAL_SERVER_ERROR</code>, make the
* <code>Throwable</code> leading to the error available as the value of the
* <code>RequestDispatcher.ERROR_EXCEPTION</code> request attribute, and perform
* an error dispatch to generate a platform-specific error message.
* </li>
* <li>
* Complete the asynchronous processing cycle by calling <code>complete()</code>.
* </li>
* </ul>
* <p>
* There can be at most one asynchronous dispatch operation per asynchronous
* cycle, which is started by a call to one of the <code>ResourceRequest#startAsync</code>
* methods. Any attempt to perform an additional asynchronous dispatch
* operation within the same asynchronous cycle will result in an
* <code>IllegalStateException</code>. When the container performs the dispatch operation,
* <code>startAsync()</code> may be invoked on the dispatched request to initiate a new
* asynchronous processing cycle, after which any of the dispatch methods or the
* <code>complete()</code> method may be called.
* </div>
*
* @throws IllegalStateException
* if called before an asynchronous processing cycle has been started,
* if one of the dispatch methods has been called but the <code>startAsync</code> method has not
* been called during the resulting dispatch, or if <code>complete()</code> was called
*/
public void dispatch() throws IllegalStateException;
/**
* <div class="changed_added_3_0">
* Dispatches the request and response objects of this <code>PortletAsyncContext</code> to
* the given path within the <code>PortletContext</code>.
* <p>
* The path parameter is interpreted in the same way as in
* <code>PortletContext#getRequestDispatcher(String)</code> scoped to
* the current portlet context.
* <p>
* There can be at most one asynchronous dispatch operation per asynchronous
* cycle, which is started by a call to one of the <code>ResourceRequest#startAsync</code>
* methods. Any attempt to perform an additional asynchronous dispatch
* operation within the same asynchronous cycle will result in an
* <code>IllegalStateException</code>. When the container performs the dispatch operation,
* <code>startAsync()</code> may be invoked on the dispatched request to initiate a new
* asynchronous processing cycle, after which any of the dispatch methods or the
* <code>complete()</code> method may be called.
* <p>
* See {@link #dispatch()} for additional details, including error handling.
* </div>
*
* @param path the path of the dispatch target, scoped to the PortletContext from which
* this PortletAsyncContext was initialized
* @throws IllegalStateException
* if called before an asynchronous processing cycle has been started,
* if one of the dispatch methods has been called but the <code>startAsync</code> method has not
* been called during the resulting dispatch, or if <code>complete()</code> was called
*/
public void dispatch(String path) throws IllegalStateException;
/**
* <div class="changed_added_3_0">
* Gets the request that was used to initialize this <code>PortletAsyncContext</code> by calling
* <code>ResourceRequest.startAsync()</code> or <code>ResourceRequest.startAsync(ServletRequest, ServletResponse)</code>.
* </div>
*
* @return The resource request object
* @throws IllegalStateException
* if one of the dispatch methods has been called but the <code>startAsync</code> method has not
* been called during the resulting dispatch, or if <code>complete()</code> was called
*/
public ResourceRequest getResourceRequest() throws IllegalStateException;
/**
* <div class="changed_added_3_0">
* Gets the response that was used to initialize this <code>PortletAsyncContext</code> by calling
* <code>ResourceRequest.startAsync()</code> or <code>ResourceRequest.startAsync(ServletRequest, ServletResponse)</code>.
* </div>
*
* @return The resource response object
* @throws IllegalStateException
* if one of the dispatch methods has been called but the <code>startAsync</code> method has not
* been called during the resulting dispatch, or if <code>complete()</code> was called
*/
public ResourceResponse getResourceResponse() throws IllegalStateException;
/**
* <div class="changed_added_3_0">
* Gets the timeout (in milliseconds) for this PortletAsyncContext.
* <p>
* This method returns the container's default timeout for asynchronous operations,
* or the timeout value passed to the most recent invocation of
* <code>setTimeout(long)</code>.
* <p>
* A timeout value of zero or less indicates no timeout.
* </div>
*
* @return the timeout in milliseconds
*/
public long getTimeout();
/**
* <div class="changed_added_3_0">
* Checks if this <code>PortletAsyncContext</code> was initialized with the original or
* application-wrapped request and response objects.
* <p>
* This information may be used by filters invoked in the outbound direction, after
* a request was put into asynchronous mode, to determine whether any request
* and/or response wrappers that they added during their inbound invocation need to
* be preserved for the duration of the asynchronous operation, or may be released.
* </div>
*
* @return
* <code>true</code> if this <code>PortletAsyncContext</code> was initialized with the original
* request and response objects by calling <code>ResourceRequest.startAsync()</code>,
* or if it was initialized by calling
* <code>ResourceRequest.startAsync(ResourceRequest, ResourceResponse)</code>, and neither
* the <code>ResourceRequest</code> nor <code>ResourceResponse</code> arguments carried any
* application-provided wrappers; <code>false</code> otherwise
*/
public boolean hasOriginalRequestAndResponse();
/**
* <div class="changed_added_3_0">
* Sets the timeout (in milliseconds) for this <code>PortletAsyncContext</code>.
* <p>
* The timeout applies to this <code>PortletAsyncContext</code> once the
* container-initiated dispatch
* during which one of the <code>ResourceRequest.startAsync()</code> methods was
* called has returned to the container.
* <p>
* The timeout will expire if neither the <code>complete()</code> method nor any of
* the dispatch
* methods are called. A timeout value of zero or less indicates no timeout.
* <p>
* If <code>setTimeout(long)</code> is not called, then the container's default timeout,
* which is available via a call to <code>getTimeout()</code>, will apply.
* <p>
* The default value is 30000 ms.
* </div>
*
* @param time the timeout in milliseconds
*/
public void setTimeout(long time);
/**
* <div class="changed_added_3_0">
* Causes the container to dispatch a thread, possibly from a managed thread pool,
* to run the specified <code>Runnable</code>. The container may propagate appropriate
* contextual information to the <code>Runnable</code>.
* </div>
*
* @param run the asynchronous handler
* @throws IllegalStateException
* if this method is called before an asynchronous processing cycle was started,
* after it has already been completed, or after a call to
* one of the <code>dispatch()</code> methods
*
**/
public void start(Runnable run) throws IllegalStateException;
}