001 package controlFactory;
002
003 import java.util.HashMap;
004 import java.io.Serializable;
005
006 /**
007 * <p>Demonstrates use of a control factory.</p>
008 *
009 * <p>A control factory is used to dynamically create multiple
010 * instances of a Service control. When all instances of the
011 * Service control have returned results, a callback is sent
012 * to the client listing the result of each Service control.</p>
013 * @common:xmlns namespace="http://openuri.org/bea/samples/workshop/controlFactory" prefix="ns0"
014 * @common:target-namespace namespace="http://workshop.bea.com/ServiceFactoryClient"
015 */
016 public class ServiceFactoryClient implements com.bea.jws.WebService
017 {
018 /**
019 * @common:control
020 */
021 private controlFactory.SlowServiceControlFactory m_services;
022
023 int m_numServices;
024 int m_numServicesReturned;
025 HashMap m_serviceHash;
026 Result [] m_results;
027
028 /**
029 * A utility class used to collect and return results
030 */
031 public static class Result implements Serializable
032 {
033 public String name;
034 public long time;
035
036 public Result(){};
037 }
038
039 public Callback callback;
040
041 public interface Callback
042 {
043 /**
044 * Callback used to return results to the client. An array
045 * of Result objects is serialized into the outgoing XML
046 * message using an XQuery map.
047 *
048 * @jws:conversation phase="finish"
049 * @jws:parameter-xml schema-element="ns0:completeServices" xquery::
050 * declare namespace ns0="http://workshop.bea.com/ServiceFactoryClient"
051 * declare namespace ns1="http://openuri.org/bea/samples/workshop/controlFactory"
052 *
053 * let $i := $input/ns0:result
054 * return
055 * <ns1:completeServices>
056 * <ns1:result>
057 * {for $r in $i/ns0:Result
058 * return
059 * <ns1:service>
060 * <ns1:name>{data($r/ns0:name)}</ns1:name>
061 * <ns1:time>{data($r/ns0:time)}</ns1:time>
062 * </ns1:service>}
063 * </ns1:result>
064 * </ns1:completeServices>::
065 */
066 public void allServicesComplete(Result [] result);
067 }
068
069 /**
070 * <p>Launch the number of instances of the service control that
071 * are specified by <b>numServices</b>.</p>
072 *
073 * @common:operation
074 * @jws:conversation phase="start"
075 */
076 public void startServices(int numServices)
077 {
078 int i;
079
080 if(numServices > 0)
081 {
082 m_numServices = numServices;
083 m_numServicesReturned = 0;
084 m_serviceHash = new HashMap();
085 m_results = new Result[numServices];
086
087 for(i=0; i<numServices; i++)
088 {
089 String serviceName = "Service" + i;
090
091 // use the control factory's create method to create a control instance
092 controlFactory.SlowServiceControl service = m_services.create();
093
094 // use the control like you would any other control
095 service.requestInfo(serviceName);
096
097 // stash the time each control is launched, indexed by instance name
098 m_serviceHash.put(serviceName, new Long((new java.util.Date().getTime())));
099 }
100 }
101 }
102
103
104
105 /**
106 * <p>Callback handler for the control's infoReady callback.</p>
107 *
108 * <p>For a control factory, callback handlers take an extra argument that is
109 * the control instance, so that the handler code can tell which control is
110 * sending the callback.</p>
111 */
112 private void m_services_infoReady(SlowServiceControl service, String name)
113 {
114 // compute how many seconds since this control was launched
115 long timeTaken = (new java.util.Date().getTime() - ((Long)m_serviceHash.get(name)).longValue()) / 1000;
116
117 // make a new Result object and populate it with control name and time taken
118 m_results[m_numServicesReturned] = new Result();
119 m_results[m_numServicesReturned].name = name;
120 m_results[m_numServicesReturned].time = timeTaken;
121
122 // keep tack of how many services have returned
123 m_numServicesReturned++;
124
125 // when all services have returned, tell the client via the callback
126 if(m_numServicesReturned == m_numServices)
127 {
128 callback.allServicesComplete(m_results);
129 }
130 }
131
132 }
|