001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.developer;
038:
039: import com.sun.istack.NotNull;
040: import com.sun.istack.Nullable;
041: import com.sun.xml.ws.api.message.Packet;
042: import com.sun.xml.ws.api.pipe.Tube;
043: import com.sun.xml.ws.api.server.AsyncProvider;
044: import com.sun.xml.ws.api.server.AsyncProviderCallback;
045:
046: import javax.annotation.Resource;
047: import javax.jws.WebMethod;
048: import javax.jws.WebService;
049: import javax.xml.ws.EndpointReference;
050: import javax.xml.ws.WebServiceContext;
051: import javax.xml.ws.WebServiceException;
052: import javax.xml.ws.wsaddressing.W3CEndpointReference;
053:
054: /**
055: * Stateful web service support in the JAX-WS RI.
056: *
057: * <h2>Usage</h2>
058: * <p>
059: * Application service implementation classes (or providers) who'd like
060: * to use the stateful web service support must declare {@link Stateful}
061: * annotation on a class. It should also have a <b>public static</b> method/field
062: * that takes {@link StatefulWebServiceManager}.
063: *
064: * <pre>
065: * @{@link Stateful} @{@link WebService}
066: * class BankAccount {
067: * protected final int id;
068: * private int balance;
069: *
070: * BankAccount(int id) { this.id = id; }
071: * @{@link WebMethod}
072: * public synchronized void deposit(int amount) { balance+=amount; }
073: *
074: * // either via a public static field
075: * <font color=red>
076: * public static {@link StatefulWebServiceManager}<BankAccount> manager;
077: * </font>
078: * // ... or via a public static method (the method name could be anything)
079: * <font color=red>
080: * public static void setManager({@link StatefulWebServiceManager}<BankAccount> manager) {
081: * ...
082: * }
083: * </font>
084: * }
085: * </pre>
086: *
087: * <p>
088: * After your service is deployed but before you receive a first request,
089: * the resource injection occurs on the field or the method.
090: *
091: * <p>
092: * A stateful web service class does not need to have a default constructor.
093: * In fact, most of the time you want to define a constructor that takes
094: * some arguments, so that each instance carries certain state (as illustrated
095: * in the above example.)
096: *
097: * <p>
098: * Each instance of a stateful web service class is identified by an unique
099: * {@link EndpointReference}. Your application creates an instance of
100: * a class, then you'll have the JAX-WS RI assign this unique EPR for the
101: * instance as follows:
102: *
103: * <pre>
104: * @{@link WebService}
105: * class Bank { // this is ordinary stateless service
106: * @{@link WebMethod}
107: * public synchronized W3CEndpointReference login(int accountId, int pin) {
108: * if(!checkPin(pin))
109: * throw new AuthenticationFailedException("invalid pin");
110: * BankAccount acc = new BankAccount(accountId);
111: * return BankAccount.manager.{@link #export export}(acc);
112: * }
113: * }
114: * </pre>
115: *
116: * <p>
117: * Typically you then pass this EPR to remote systems. When they send
118: * messages to this EPR, the JAX-WS RI makes sure that the particular exported
119: * instance associated with that EPR will receive a service invocation.
120: *
121: * <h2>Things To Consider</h2>
122: * <p>
123: * When you no longer need to tie an instance to the EPR,
124: * use {@link #unexport(Object)} so that the object can be GC-ed
125: * (or else you'll leak memory.) You may choose to do so explicitly,
126: * or you can rely on the time out by using {@link #setTimeout(long, Callback)}.
127: *
128: * <p>
129: * {@link StatefulWebServiceManager} is thread-safe. It can be safely
130: * invoked from multiple threads concurrently.
131: *
132: * @author Kohsuke Kawaguchi
133: * @see StatefulFeature
134: * @since 2.1
135: */
136: public interface StatefulWebServiceManager<T> {
137: /**
138: * Exports an object.
139: *
140: * <p>
141: * This method works like {@link #export(Object)} except that
142: * you can obtain the EPR in your choice of addressing version,
143: * by passing in the suitable <tt>epr</tt> parameter.
144: *
145: * @param epr
146: * Either {@link W3CEndpointReference} or {@link MemberSubmissionEndpointReference}.
147: * If other types are specified, this method throws an {@link WebServiceException}.
148: * @return
149: * {@link EndpointReference}-subclass that identifies this exported
150: * object.
151: */
152: @NotNull
153: <EPR extends EndpointReference> EPR export(Class<EPR> epr, T o);
154:
155: /**
156: * Exports an object.
157: *
158: * <p>
159: * This method works like {@link #export(Object)} except that
160: * you can obtain the EPR in your choice of addressing version,
161: * by passing in the suitable <tt>epr</tt> parameter.
162: *
163: * @param epr
164: * Either {@link W3CEndpointReference} or {@link MemberSubmissionEndpointReference}.
165: * If other types are specified, this method throws an {@link WebServiceException}.
166: * @param o
167: * The object to be exported, whose identity be referenced by the returned EPR.
168: * @param recipe
169: * The additional data to be put into EPR. Can be null.
170: * @return
171: * {@link EndpointReference}-subclass that identifies this exported
172: * object.
173: * @since 2.1.1
174: */
175: @NotNull
176: <EPR extends EndpointReference> EPR export(Class<EPR> epr, T o,
177: @Nullable
178: EPRRecipe recipe);
179:
180: /**
181: * Exports an object.
182: *
183: * <p>
184: * JAX-WS RI assigns an unique EPR to the exported object,
185: * and from now on, messages that are sent to this EPR will
186: * be routed to the given object.
187: *
188: * <p>
189: * The object will be locked in memory, so be sure to
190: * {@link #unexport(Object) unexport} it when it's no longer needed.
191: *
192: * <p>
193: * Notice that the obtained EPR contains the address of the service,
194: * which depends on the currently processed request. So invoking
195: * this method multiple times with the same object may return
196: * different EPRs, if such multiple invocations are done while
197: * servicing different requests. (Of course all such EPRs point
198: * to the same object, so messages sent to those EPRs will be
199: * served by the same instance.)
200: *
201: * @return
202: * {@link W3CEndpointReference} that identifies this exported
203: * object. Always non-null.
204: */
205: @NotNull
206: W3CEndpointReference export(T o);
207:
208: /**
209: * Exports an object (for {@link AsyncProvider asynchronous web services}.)
210: *
211: * <p>
212: * This method works like {@link #export(Class,Object)} but it
213: * takes an extra {@link WebServiceContext} that represents the request currently
214: * being processed by the caller (the JAX-WS RI remembers this when the service
215: * processing is synchronous, and that's why this parameter is only needed for
216: * asynchronous web services.)
217: *
218: * <h3>Why {@link WebServiceContext} is needed?</h3>
219: * <p>
220: * The obtained EPR contains address, such as host name. The server does not
221: * know what its own host name is (or there are more than one of them),
222: * so this value is determined by what the current client thinks the server name is.
223: * This is why we need to take {@link WebServiceContext}. Pass in the
224: * object given to {@link AsyncProvider#invoke(Object, AsyncProviderCallback,WebServiceContext)}.
225: */
226: @NotNull
227: <EPR extends EndpointReference> EPR export(Class<EPR> eprType,
228: @NotNull
229: WebServiceContext context, T o);
230:
231: /**
232: * Exports an object.
233: *
234: * <p>
235: * <b>This method is not meant for application code.</b>
236: * This is for {@link Tube}s that wish to use stateful web service support.
237: *
238: * @param currentRequest
239: * The request that we are currently processing. This is used to infer the address in EPR.
240: * @see #export(Class, WebServiceContext, Object)
241: */
242: @NotNull
243: <EPR extends EndpointReference> EPR export(Class<EPR> eprType,
244: @NotNull
245: Packet currentRequest, T o);
246:
247: /**
248: * The same as {@link #export(Class, Packet, Object)} except
249: * that it takes {@link EPRRecipe}.
250: *
251: * @param recipe
252: * See {@link #export(Class, Object, EPRRecipe)}.
253: */
254: @NotNull
255: <EPR extends EndpointReference> EPR export(Class<EPR> eprType,
256: @NotNull
257: Packet currentRequest, T o, EPRRecipe recipe);
258:
259: /**
260: * Exports an object.
261: *
262: * @deprecated
263: * This method is provided as a temporary workaround, and we'll eventually try to remove it.
264: *
265: * @param endpointAddress
266: * The endpoint address URL. Normally, this information is determined by other inputs,
267: * like {@link Packet} or {@link WebServiceContext}.
268: */
269: @NotNull
270: <EPR extends EndpointReference> EPR export(Class<EPR> eprType,
271: String endpointAddress, T o);
272:
273: /**
274: * Unexports the given instance.
275: *
276: * <p>
277: * JAX-WS will release a strong reference to unexported objects,
278: * and they will never receive further requests (requests targeted
279: * for those unexported objects will be served by the fallback object.)
280: *
281: * @param o
282: * if null, this method will be no-op.
283: */
284: void unexport(@Nullable
285: T o);
286:
287: /**
288: * Checks if the given EPR represents an object that has been exported from this manager.
289: *
290: * <p>
291: * This method can be used to have two endpoints in the same application communicate
292: * locally.
293: *
294: * @return null if the EPR is not exported from this manager.
295: */
296: @Nullable
297: T resolve(@NotNull
298: EndpointReference epr);
299:
300: /**
301: * Sets the "fallback" instance.
302: *
303: * <p>
304: * When the incoming request does not have the necessary header to
305: * distinguish instances of <tt>T</tt>, or when the header is present
306: * but its value does not correspond with any of the active exported
307: * instances known to the JAX-WS, then the JAX-WS RI will try to
308: * route the request to the fallback instance.
309: *
310: * <p>
311: * This provides the application an opportunity to perform application
312: * specific error recovery.
313: *
314: * <p>
315: * If no fallback instance is provided, then the JAX-WS RI will
316: * send back the fault. By default, no fallback instance is set.
317: *
318: * <p>
319: * This method can be invoked any time, but most often you'd like to
320: * use one instance at the get-go. The following code example
321: * illustrates how to do this:
322: *
323: * <pre>
324: * @{@link WebService}
325: * class BankAccount {
326: * ... continuting from the example in class javadoc ...
327: *
328: * @{@link Resource} static void setManager({@link StatefulWebServiceManager} manager) {
329: * manager.setFallbackInstance(new BankAccount(0) {
330: * @{@link Override}
331: * void deposit(int amount) {
332: * putToAuditRecord(id);
333: * if(thisLooksBad()) callPolice();
334: * throw new {@link WebServiceException}("No such bank account exists");
335: * }
336: * });
337: * }
338: * }
339: * </pre>
340: *
341: * @param o
342: * Can be null.
343: */
344: void setFallbackInstance(T o);
345:
346: /**
347: * Configures timeout for exported instances.
348: *
349: * <p>
350: * When configured, the JAX-WS RI will internally use a timer
351: * so that exported objects that have not received any request
352: * for the given amount of minutes will be automatically unexported.
353: *
354: * <p>
355: * At some point after the time out has occurred for an instance,
356: * the JAX-WS RI will invoke the {@link Callback} to notify the application
357: * that the time out has reached. Application then has a choice of
358: * either let the object go unexported, or {@link #touch(Object) touch}
359: * let the object live for another round of timer interval.
360: *
361: * <p>
362: * If no callback is set, the expired object will automatically unexported.
363: *
364: * <p>
365: * When you call this method multiple times, its effect on existing
366: * instances are unspecified, although deterministic.
367: *
368: * @param milliseconds
369: * The time out interval. Specify 0 to cancel the timeout timer.
370: * Note that this only guarantees that time out does not occur
371: * at least until this amount of time has elapsed. It does not
372: * guarantee that the time out will always happen right after
373: * the timeout is reached.
374: * @param callback
375: * application may choose to install a callback to control the
376: * timeout behavior.
377: */
378: void setTimeout(long milliseconds, @Nullable
379: Callback<T> callback);
380:
381: /**
382: * Resets the time out timer for the given instance.
383: *
384: * <p>
385: * If the object is null, not exported, or already unexported, this
386: * method will be no-op.
387: */
388: void touch(T o);
389:
390: /**
391: * Used by {@link StatefulWebServiceManager#setTimeout(long, Callback)}
392: * to determine what to do when the time out is reached.
393: */
394: interface Callback<T> {
395: /**
396: * Application has a chance to decide if the object should be unexported,
397: * or kept alive.
398: *
399: * <p>
400: * The application should either unexport the object, or touch the object
401: * from within this callback.
402: * If no action is taken, the object will remain exported until it is
403: * manually unexported.
404: *
405: * @param timedOutObject
406: * The object that reached the time out.
407: * @param manager
408: * The manager instance that you exported the object to.
409: */
410: void onTimeout(@NotNull
411: T timedOutObject, @NotNull
412: StatefulWebServiceManager<T> manager);
413: }
414: }
|