com.sun.xml.ws.developer.StatefulWebServiceManager Maven / Gradle / Ivy
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.xml.ws.developer;
import com.sun.istack.NotNull;
import com.sun.istack.Nullable;
import com.sun.xml.ws.api.message.Packet;
import com.sun.xml.ws.api.pipe.Tube;
import com.sun.xml.ws.api.server.AsyncProvider;
import com.sun.xml.ws.api.server.AsyncProviderCallback;
import javax.annotation.Resource;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.EndpointReference;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.wsaddressing.W3CEndpointReference;
/**
* Stateful web service support in the JAX-WS RI.
*
* Usage
*
* Application service implementation classes (or providers) who'd like
* to use the stateful web service support must declare {@link Stateful}
* annotation on a class. It should also have a public static method/field
* that takes {@link StatefulWebServiceManager}.
*
*
* @{@link Stateful} @{@link WebService}
* class BankAccount {
* protected final int id;
* private int balance;
*
* BankAccount(int id) { this.id = id; }
* @{@link WebMethod}
* public synchronized void deposit(int amount) { balance+=amount; }
*
* // either via a public static field
*
* public static {@link StatefulWebServiceManager}<BankAccount> manager;
*
* // ... or via a public static method (the method name could be anything)
*
* public static void setManager({@link StatefulWebServiceManager}<BankAccount> manager) {
* ...
* }
*
* }
*
*
*
* After your service is deployed but before you receive a first request,
* the resource injection occurs on the field or the method.
*
*
* A stateful web service class does not need to have a default constructor.
* In fact, most of the time you want to define a constructor that takes
* some arguments, so that each instance carries certain state (as illustrated
* in the above example.)
*
*
* Each instance of a stateful web service class is identified by an unique
* {@link EndpointReference}. Your application creates an instance of
* a class, then you'll have the JAX-WS RI assign this unique EPR for the
* instance as follows:
*
*
* @{@link WebService}
* class Bank { // this is ordinary stateless service
* @{@link WebMethod}
* public synchronized W3CEndpointReference login(int accountId, int pin) {
* if(!checkPin(pin))
* throw new AuthenticationFailedException("invalid pin");
* BankAccount acc = new BankAccount(accountId);
* return BankAccount.manager.{@link #export export}(acc);
* }
* }
*
*
*
* Typically you then pass this EPR to remote systems. When they send
* messages to this EPR, the JAX-WS RI makes sure that the particular exported
* instance associated with that EPR will receive a service invocation.
*
*
Things To Consider
*
* When you no longer need to tie an instance to the EPR,
* use {@link #unexport(Object)} so that the object can be GC-ed
* (or else you'll leak memory.) You may choose to do so explicitly,
* or you can rely on the time out by using {@link #setTimeout(long, Callback)}.
*
*
* {@link StatefulWebServiceManager} is thread-safe. It can be safely
* invoked from multiple threads concurrently.
*
* @author Kohsuke Kawaguchi
* @see StatefulFeature
* @since 2.1
*/
public interface StatefulWebServiceManager {
/**
* Exports an object.
*
*
* This method works like {@link #export(Object)} except that
* you can obtain the EPR in your choice of addressing version,
* by passing in the suitable epr parameter.
*
* @param epr
* Either {@link W3CEndpointReference} or {@link MemberSubmissionEndpointReference}.
* If other types are specified, this method throws an {@link WebServiceException}.
* @return
* {@link EndpointReference}-subclass that identifies this exported
* object.
*/
@NotNull EPR export(Class epr, T o);
/**
* Exports an object.
*
*
* This method works like {@link #export(Object)} except that
* you can obtain the EPR in your choice of addressing version,
* by passing in the suitable epr parameter.
*
* @param epr
* Either {@link W3CEndpointReference} or {@link MemberSubmissionEndpointReference}.
* If other types are specified, this method throws an {@link WebServiceException}.
* @param o
* The object to be exported, whose identity be referenced by the returned EPR.
* @param recipe
* The additional data to be put into EPR. Can be null.
* @return
* {@link EndpointReference}-subclass that identifies this exported
* object.
* @since 2.1.1
*/
@NotNull EPR export(Class epr, T o, @Nullable EPRRecipe recipe );
/**
* Exports an object.
*
*
* JAX-WS RI assigns an unique EPR to the exported object,
* and from now on, messages that are sent to this EPR will
* be routed to the given object.
*
*
* The object will be locked in memory, so be sure to
* {@link #unexport(Object) unexport} it when it's no longer needed.
*
*
* Notice that the obtained EPR contains the address of the service,
* which depends on the currently processed request. So invoking
* this method multiple times with the same object may return
* different EPRs, if such multiple invocations are done while
* servicing different requests. (Of course all such EPRs point
* to the same object, so messages sent to those EPRs will be
* served by the same instance.)
*
* @return
* {@link W3CEndpointReference} that identifies this exported
* object. Always non-null.
*/
@NotNull W3CEndpointReference export(T o);
/**
* Exports an object (for {@link AsyncProvider asynchronous web services}.)
*
*
* This method works like {@link #export(Class,Object)} but it
* takes an extra {@link WebServiceContext} that represents the request currently
* being processed by the caller (the JAX-WS RI remembers this when the service
* processing is synchronous, and that's why this parameter is only needed for
* asynchronous web services.)
*
*
Why {@link WebServiceContext} is needed?
*
* The obtained EPR contains address, such as host name. The server does not
* know what its own host name is (or there are more than one of them),
* so this value is determined by what the current client thinks the server name is.
* This is why we need to take {@link WebServiceContext}. Pass in the
* object given to {@link AsyncProvider#invoke(Object, AsyncProviderCallback,WebServiceContext)}.
*/
@NotNull EPR export(Class eprType, @NotNull WebServiceContext context, T o);
/**
* Exports an object.
*
*
* This method is not meant for application code.
* This is for {@link Tube}s that wish to use stateful web service support.
*
* @param currentRequest
* The request that we are currently processing. This is used to infer the address in EPR.
* @see #export(Class, WebServiceContext, Object)
*/
@NotNull EPR export(Class eprType, @NotNull Packet currentRequest, T o);
/**
* The same as {@link #export(Class, Packet, Object)} except
* that it takes {@link EPRRecipe}.
*
* @param recipe
* See {@link #export(Class, Object, EPRRecipe)}.
*/
@NotNull EPR export(Class eprType, @NotNull Packet currentRequest, T o, EPRRecipe recipe);
/**
* Exports an object.
*
* @deprecated
* This method is provided as a temporary workaround, and we'll eventually try to remove it.
*
* @param endpointAddress
* The endpoint address URL. Normally, this information is determined by other inputs,
* like {@link Packet} or {@link WebServiceContext}.
*/
@NotNull EPR export(Class eprType, String endpointAddress, T o);
/**
* Unexports the given instance.
*
*
* JAX-WS will release a strong reference to unexported objects,
* and they will never receive further requests (requests targeted
* for those unexported objects will be served by the fallback object.)
*
* @param o
* if null, this method will be no-op.
*/
void unexport(@Nullable T o);
/**
* Checks if the given EPR represents an object that has been exported from this manager.
*
*
* This method can be used to have two endpoints in the same application communicate
* locally.
*
* @return null if the EPR is not exported from this manager.
*/
@Nullable T resolve(@NotNull EndpointReference epr);
/**
* Sets the "fallback" instance.
*
*
* When the incoming request does not have the necessary header to
* distinguish instances of T, or when the header is present
* but its value does not correspond with any of the active exported
* instances known to the JAX-WS, then the JAX-WS RI will try to
* route the request to the fallback instance.
*
*
* This provides the application an opportunity to perform application
* specific error recovery.
*
*
* If no fallback instance is provided, then the JAX-WS RI will
* send back the fault. By default, no fallback instance is set.
*
*
* This method can be invoked any time, but most often you'd like to
* use one instance at the get-go. The following code example
* illustrates how to do this:
*
*
* @{@link WebService}
* class BankAccount {
* ... continuting from the example in class javadoc ...
*
* @{@link Resource} static void setManager({@link StatefulWebServiceManager} manager) {
* manager.setFallbackInstance(new BankAccount(0) {
* @{@link Override}
* void deposit(int amount) {
* putToAuditRecord(id);
* if(thisLooksBad()) callPolice();
* throw new {@link WebServiceException}("No such bank account exists");
* }
* });
* }
* }
*
*
* @param o
* Can be null.
*/
void setFallbackInstance(T o);
/**
* Configures timeout for exported instances.
*
*
* When configured, the JAX-WS RI will internally use a timer
* so that exported objects that have not received any request
* for the given amount of minutes will be automatically unexported.
*
*
* At some point after the time out has occurred for an instance,
* the JAX-WS RI will invoke the {@link Callback} to notify the application
* that the time out has reached. Application then has a choice of
* either let the object go unexported, or {@link #touch(Object) touch}
* let the object live for another round of timer interval.
*
*
* If no callback is set, the expired object will automatically unexported.
*
*
* When you call this method multiple times, its effect on existing
* instances are unspecified, although deterministic.
*
* @param milliseconds
* The time out interval. Specify 0 to cancel the timeout timer.
* Note that this only guarantees that time out does not occur
* at least until this amount of time has elapsed. It does not
* guarantee that the time out will always happen right after
* the timeout is reached.
* @param callback
* application may choose to install a callback to control the
* timeout behavior.
*/
void setTimeout(long milliseconds, @Nullable Callback callback);
/**
* Resets the time out timer for the given instance.
*
*
* If the object is null, not exported, or already unexported, this
* method will be no-op.
*/
void touch(T o);
/**
* Used by {@link StatefulWebServiceManager#setTimeout(long, Callback)}
* to determine what to do when the time out is reached.
*/
interface Callback {
/**
* Application has a chance to decide if the object should be unexported,
* or kept alive.
*
*
* The application should either unexport the object, or touch the object
* from within this callback.
* If no action is taken, the object will remain exported until it is
* manually unexported.
*
* @param timedOutObject
* The object that reached the time out.
* @param manager
* The manager instance that you exported the object to.
*/
void onTimeout(@NotNull T timedOutObject, @NotNull StatefulWebServiceManager manager);
}
}