001 package async;
002
003 import com.bea.control.JwsContext;
004
005 /**
006 * <p>Demonstrates use of the @jws:conversation tag to manage the lifetime of the service
007 * and provide data persistence and message correlation.</p>
008 *
009 * <p>Remember that multiple clients might invoke a web service simultaneously. When the
010 * web service stores data relevant to the client or calls additional services
011 * in order to process a client's request, the service must be able to process returned
012 * data from the external services in the context of the specific client it relates
013 * to. This is all automatic when conversations are used.</p>
014 *
015 * <p>This service uses an external service that is asynchronous, but exposes polling
016 * methods in addition to callbacks so that a client that can't accept callbacks
017 * can use it.</p>
018 *
019 * <p>Remember that not all clients are capable of accepting callbacks. Specifically,
020 * clients operating from behind firewalls may not be able to receive asynchronous
021 * callbacks. You may wish to provide a synchronous interface, like this one,
022 * for such clients. If a client can accept callbacks, it must send a callbackURL
023 * as part of any "start conversation" method invocation. The callbackURL is
024 * available via the getCallbackLocation method of the JwsContext interface,
025 * which is available in all WebLogic web services.</p>
026 *
027 * <p>To see the behavior in the Test View, invoke startRequest and then getRequestStatus
028 * several times quickly. Examine the results of the calls to testHelloAsync.
029 * The result of getRequestStatus will change once the timer in HelloWorldAsync
030 * has expired.</p>
031 * @common:target-namespace namespace="http://workshop.bea.com/Conversation"
032 */
033 public class Conversation implements com.bea.jws.WebService
034 {
035 /**
036 * @common:control
037 */
038 private HelloWorldAsyncControl helloAsync;
039
040 /**
041 * @common:context
042 */
043 JwsContext context;
044
045 /**
046 * <p>This variable holds what the HelloWorldAsync service has sent back, if anything.
047 * By designating the methods of this web service as part of a conversation
048 * with the @common:conversation tags, member variables of this web service
049 * automatically become persistent for the duration of the conversation.</p>
050 */
051 private String helloAsyncReturn;
052
053 /**
054 * <p>This variable holds the callbackURL of the client. It is obtained from the
055 * JwsContext interface during the "start" method of the conversation. If the client
056 * does not supply a callback URL, then callbacks cannot be sent to the client.
057 *
058 * In this web service, we'll assume that if the client can't accept callbacks it
059 * will use the polling interface (getRequestStatus) to get the current state and
060 * it will use terminateRequest when the client is done using this web service.</p>
061 */
062 private String callbackURL = null;
063
064 public Callback callback;
065
066 public interface Callback
067 {
068 /**
069 * Callback to invoke on the client when the external service
070 * returns its result. Will only be called it the client can
071 * accept callbacks and told us where to send them.
072 *
073 * If this callback is used, it implicitly terminates the
074 * conversation with no action required on the part of the
075 * client.
076 *
077 * @jws:conversation phase="finish"
078 */
079 public void onResultReady(String result);
080 }
081
082
083
084 /**
085 * <p>Starts the conversation and makes a request to the HelloWorldAsync service.
086 * To continue the sample after calling this method, click the conversation ID in the
087 * log, then select getRequestStatus until the request is fulfilled. Then click
088 * terminateRequest.</p>
089 *
090 * <p>Pass in <b>false</b> for useCallbacks to simulate a client that cannot accept
091 * callbacks.</p>
092 *
093 * <p>Pass in <b>true</b> for useCallbacks to allow callbacks.</p>
094 *
095 * @common:operation
096 * @jws:conversation phase="start"
097 */
098 public void startRequest(boolean useCallbacks)
099 {
100 /*
101 * The servlet that underlies Test View can receive callbacks, so
102 * we can't demonstrate a client that cannot accept callbacks unless
103 * we provide an explicit way for the client to say not to use them.
104 * If you specify 'false' for useCallbacks in Test View when using this
105 * web service, it will behave as though the client cannot accept
106 * callbacks.
107 */
108 if( useCallbacks ) {
109 callbackURL = context.getCallbackLocation();
110 }
111 // start the HelloWorldAsync service.
112 helloAsync.HelloAsync();
113 }
114
115 /**
116 * <p>getRequestStatus is used to poll Conversation.jws to determine whether
117 * we've heard back from HelloWorldAsync.</p>
118 *
119 * @common:operation
120 * @jws:conversation phase="continue"
121 */
122 public String getRequestStatus()
123 {
124 if (helloAsyncReturn == null)
125 return "HelloAsync has not yet returned it's message";
126 else
127 return "HelloAsync said: '" + helloAsyncReturn + "'";
128 }
129
130 /**
131 * <p>Used to tell Conversation.jws that the current conversation is
132 * no longer needed.</p>
133 *
134 * @common:operation
135 * @jws:conversation phase="finish"
136 */
137 public void terminateRequest()
138 { }
139
140 /**
141 * <p>Handler for HelloWorldAsync's HelloResult callback.</p>
142 *
143 * <p>Store HelloWorldAsync's response in a member variable so that future calls to
144 * testHelloAsync will give the current status.</p>
145 */
146 public void helloAsync_onHelloResult(java.lang.String hello)
147 {
148 helloAsyncReturn = hello;
149
150 /*
151 * If the client can accept callbacks, use the callback to send the result.
152 * Since onResultReady is marked phase="finish", the conversation will be
153 * terminated after this call with no further action required from the
154 * client.
155 */
156 if( callbackURL != null ) {
157 callback.onResultReady(hello);
158 }
159 }
160 }
|