View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.ksb.api.bus;
17  
18  import java.util.List;
19  import java.util.Map;
20  
21  import javax.xml.namespace.QName;
22  
23  /**
24   * The {@code ServiceBus} is the primary api that client applications use to interact with the Kuali
25   * Service Bus. It provides capabilities to retrieve services endpoints for use when needing to
26   * invoke a service. It also provides a mechanism by which a client application can publish it's own
27   * services to the bus.
28   * 
29   * <p>
30   * The service bus may be backed by a service registry which can be used to locate services which
31   * other applications have published to the service registry. The service bus will synchronize it's
32   * known state with the of the registry, either through explicit invocations of the
33   * {@link #synchronize()} method or on a periodic basis (the details of which are up to the
34   * implementation).
35   * 
36   * <p>
37   * Note that the {@code ServiceBus} manages two primary collections of {@link Endpoint} classes.
38   * Those that have been published by this application (referred to as "local" endpoints) and those
39   * which have been published by other applications (referred to as "remote" endpoints).
40   * 
41   * @see Endpoint
42   * @see ServiceConfiguration
43   * @see ServiceDefinition
44   * 
45   * @author Kuali Rice Team (rice.collab@kuali.org)
46   * 
47   */
48  public interface ServiceBus {
49  
50      /**
51       * Returns the instance ID which identifies this client application to the service bus. The
52       * instance ID should be unique for each client of the service bus and will never be blank or
53       * null.
54       * 
55       * @return the instance ID for the application in which this service bus client is resident
56       */
57      String getInstanceId();
58  
59      /**
60       * Returns an unmodifiable list of accessible endpoints that are available to the service bus
61       * with the given service name. This method will only return endpoints that the service bus
62       * believes are online, endpoints which are offline will not be included. In certain cases a
63       * specific service endpoint will be available both as a local and remote service. In these
64       * cases, the list returned from this method will preferentially include the local service. It
65       * will *not* include both the local and remote endpoint to the same service. This is important
66       * as this method may be used to get endpoints for broadcasting service calls to all endpoints
67       * with a given name. In these cases, it is not desirable to invoke the same endpoint twice.
68       * 
69       * @return a list of the remote endpoints that are available for the given service name, this
70       *         list will never be null but may be empty if there are no remote endpoints for the
71       *         given service name
72       * @throws IllegalArgumentException if serviceName is null
73       */
74      List<Endpoint> getEndpoints(QName serviceName);
75      
76      /**
77       * Returns an unmodifiable list of accessible endpoints that are available to the service bus
78       * with the given service name for the given application id. This method will only return
79       * endpoints that the service bus believes are online, endpoints which are offline will not be
80       * included. In certain cases a specific service endpoint will be available both as a local and
81       * remote service. In these cases, the list returned from this method will preferentially
82       * include the local service. It will *not* include both the local and remote endpoint to the
83       * same service. This is important as this method may be used to get endpoints for broadcasting
84       * service calls to all endpoints with a given name. In these cases, it is not desirable to
85       * invoke the same endpoint twice.
86       * @param serviceName the name of the service for which to locate an available endpoint
87       * @param applicationId the id of the application for which to locate an available endpoint for
88       *        the given service name
89       * @return a list of the remote endpoints that are available for the given service name, this
90       *         list will never be null but may be empty if there are no remote endpoints for the
91       *         given service name
92       * @throws IllegalArgumentException if serviceName is null
93       * @since 2.1.1
94       */
95      List<Endpoint> getEndpoints(QName serviceName, String applicationId);
96  
97      /**
98       * Returns an unmodifiable list of remotely accessible endpoints that are available in the
99       * service registry with the given service name. This method will only return endpoints that the
100      * service bus believes are online, endpoints which are offline will not be included.
101      * 
102      * <p>
103      * If the service bus client has also deployed a service with this name, a remoted endpoint to
104      * this service will likely also be included in this list assuming that endpoint has already
105      * been synchronized with the registry.
106      * 
107      * <p>
108      * In most cases, it is preferable to use {@link #getEndpoints(QName)} instead of this method.
109      * Because it will preferably return a local endpoint reference for a given service endpoint if
110      * one is available.
111      * 
112      * @return a list of all endpoints that are available for the given service name, this list will
113      *         never be null but may be empty if there are no endpoints for the given service name
114      * @throws IllegalArgumentException if serviceName is null
115      */
116     List<Endpoint> getRemoteEndpoints(QName serviceName);
117 
118     /**
119      * Returns the endpoint for the service with the given name that was published by this service
120      * bus client. If this client has not published any such service, then this method will return
121      * null.
122      * 
123      * @param serviceName the name of the service represented by the local endpoint
124      * @return the local endpoint for the given service name which was deployed by this client, or
125      *         null if no such service has been published
126      * @throws IllegalArgumentException if serviceName is null
127      */
128     Endpoint getLocalEndpoint(QName serviceName);
129 
130     /**
131      * Returns an unmodifiable list of all services that have been published by this service bus
132      * client.
133      * 
134      * @return a map with the local service name as the key and the local endpoint as the value
135      *         which contains all local services published by this service bus client. This map may
136      *         be empty if this client has published no services, but it should never be null.
137      */
138     Map<QName, Endpoint> getLocalEndpoints();
139 
140     /**
141      * Returns an unmodifiable list of all available and online endpoints of which the service bus
142      * is aware, including both local and remote endpoints.
143      * 
144      * @return all available endpoints, this list may be empty if no endpoints exist but will never
145      *         be null
146      */
147     List<Endpoint> getAllEndpoints();
148 
149     /**
150      * Returns an available endpoint for the service with the given name. If the service with the
151      * given name is published locally, preference will be given to the locally deployed version of
152      * the service.
153      * 
154      * <p>
155      * Based on the nature of this method, if there is more than one endpoint available for the
156      * given name, multiple invocations of this method with the same service name may return
157      * different {@link Endpoint} instances each time.
158      * 
159      * @param serviceName the name of the service for which to locate an available endpoint
160      * @return an available endpoint for the service with the given name, or null if none is
161      *         available
162      * @throws IllegalArgumentException if serviceName is null
163      */
164     Endpoint getEndpoint(QName serviceName);
165 
166     /**
167      * Returns an available endpoint for the service with the given name which is hosted by the
168      * application with the given application id. This operation functions the same as
169      * {@link #getEndpoint(QName)} with the exception that it will only consider endpoints with the
170      * given application id.
171      * 
172      * <p>
173      * Invoking this method with a null or blank value for {@code applicationId} is equivalent to
174      * invoking {@link #getEndpoint(QName)}.
175      * 
176      * @param serviceName the name of the service for which to locate an available endpoint
177      * @param applicationId the id of the application for which to locate an available endpoint for
178      *        the given service name
179      * @return an available endpoint for the service with the given name and application id, or null
180      *         if none is available
181      * @throws IllegalArgumentException if serviceName is null
182      */
183     Endpoint getEndpoint(QName serviceName, String applicationId);
184 
185     /**
186      * Returns the endpoint matching the given service configuration, if one exists. In the case of
187      * services published by this service bus client, this method will preferably return the local
188      * endpoints in place of a remote endpoint to the same service.
189      * 
190      * @param serviceConfiguration the service configuration by which to lookup up the endpoint
191      * @return the endpoint who's service configuration matches the given configuration, or null if
192      *         no such match could be determined
193      * @throws IllegalArgumentException if the given serviceConfiguration is null
194      */
195     Endpoint getConfiguredEndpoint(ServiceConfiguration serviceConfiguration);
196 
197     /**
198      * Returns a proxy to the service with the given name. This proxy should have built-in support
199      * for fail-over and load balancing capabilities. This means it is safe for client applications
200      * to cache a reference to this service proxy.
201      * 
202      * <p>
203      * This proxy should additionally be thread-safe.
204      * 
205      * <p>
206      * This method is equivalent to invoking {@link #getEndpoint(QName).getService()}.
207      * 
208      * @param serviceName the name of the service for which to locate an available proxy
209      * @return an available proxy for the service with the given name, or null if none is available
210      * @throws IllegalArgumentException if serviceName is null
211      */
212     Object getService(QName serviceName);
213 
214     /**
215      * Returns a proxy to the service with the given name which is hosted by the application with
216      * the given application id. This operation functions the same as {@link #getService(QName)}
217      * with the exception that it will only consider endpoints with the given application id.
218      * 
219      * <p>
220      * Invoking this method with a null or blank value for {@code applicationId} is equivalent to
221      * invoking {@link #getService(QName)}. This method is also equivalent to invoking
222      * {@link #getEndpoint(QName, String).getService()}.
223      * 
224      * @param serviceName the name of the service for which to locate an available proxy
225      * @param applicationId the id of the application for which to locate an available proxy for the
226      *        given service name
227      * @return an available proxy for the service with the given name, or null if none is available
228      * @throws IllegalArgumentException if serviceName is null
229      */
230     Object getService(QName serviceName, String applicationId);
231 
232     /**
233      * Publish a service with the given ServiceDefinition to the service bus. This effectively
234      * updates the service registry and provides an endpoint for other applications to invoke. If
235      * this application has already published a service under this name, it will be updated instead
236      * to reflect the new ServiceDefinition.
237      * 
238      * <p>
239      * The method also provides the ability for the service bus to immediately synchronize with the
240      * service registry after registering the service if {@code synchronize} is set to {@code true}.
241      * 
242      * @see #synchronize()
243      * 
244      * @param serviceDefinition the definition of the service to publish, must not be null
245      * @param synchronize indicates whether or not this service bus client should immediately
246      *        synchronize it's changes with the registry after registering the service.
247      * @return the service configuration for the published service
248      * @throws IllegalArgumentException if serviceDefinition is null
249      */
250     ServiceConfiguration publishService(ServiceDefinition serviceDefinition, boolean synchronize);
251 
252     /**
253      * Functions as per {@link #publishService(ServiceDefinition, boolean)} but allows for multiple
254      * services to be published to the bus in a single operation. If the given list of service
255      * definitions is empty then this method will do nothing (including skipping synchronization
256      * with the registry if that was requested).
257      * 
258      * @see #publishService(ServiceDefinition, boolean)
259      * @see #synchronize()
260      * 
261      * @param serviceDefinitions the list of definition for the services to publish, must not be
262      *        null
263      * @param synchronize indicates whether or not this service bus client should immediately
264      *        synchronize it's changes with the registry after registering the services.
265      * @return the list of service configurations for the published services in the same order as
266      *         the list of service definitions
267      * @throws IllegalArgumentException if serviceDefinitions is null
268      */
269     List<ServiceConfiguration> publishServices(List<ServiceDefinition> serviceDefinitions, boolean synchronize);
270 
271     /**
272      * Removes the service from the service bus and the service registry with the given service
273      * name. Client applications should only be able to remove services that they themselves have
274      * published.
275      * 
276      * <p>
277      * This method also provides the ability for the service bus to immediately synchronize with the
278      * service registry after removing the service if {@code synchronize} is set to {@code true}. If
279      * the service is not located and successfully removed, however, the sychronization will not
280      * run.
281      * 
282      * @see #synchronize()
283      * 
284      * @param serviceName the name of the service to remove
285      * @param synchronize indicates whether or not this service bus client should immediately
286      *        synchronize after removing the service
287      * @return true if the service was removed, false otherwise
288      * @throws IllegalArgumentException if the given serviceName is null
289      */
290     boolean removeService(QName serviceName, boolean synchronize);
291 
292     /**
293      * Functions as per {@link #removeService(QName, boolean)} but allows for multiple services to
294      * be removed from the bus in a single operation. If the given list of service names is empty
295      * then this method will do nothing (including skipping synchronization with the registry if
296      * that was requested).
297      * 
298      * <p>
299      * If the list returned from the method contains only false responses (meaning that no services
300      * were removed) this method will skip synchronization even if it is requested.
301      * 
302      * @see #removeService(QName, boolean)
303      * @see #synchronize()
304      * 
305      * @param serviceNames the list of names for the services to remove, must not be null
306      * @param synchronize indicates whether or not this service bus client should immediately
307      *        synchronize it's changes with the registry after removing the services.
308      * @return a list of Booleans indicating which of the service removals were successful. This
309      *         list will be in the same order as the list of service configurations that were passed
310      *         in.
311      * @throws IllegalArgumentException if serviceNames is null
312      */
313     List<Boolean> removeServices(List<QName> serviceNames, boolean synchronize);
314 
315     /**
316      * Synchronizes the current client's service bus with the central service registry. This may be
317      * done automatically on a periodic basic depending on the implementation of this service, but
318      * can be invoked manually through this method. This method should both register any outstanding
319      * service publications to the registry, as well as detect any changes in remote services that
320      * have been published/removed by other applications in the registry and update local service
321      * bus state accordingly.
322      *
323      * <p>Invoking this method is equivalent to invoking {@link #synchronizeLocalServices()} and
324      * {@link #synchronizeRemoteServices()} in either order.  However, the semantics vary slightly
325      * as this method should attempt to invoke them as an atomic operation.</p>
326      */
327     void synchronize();
328 
329     /**
330      * Fetches information about the current state of the remote services available in the registry
331      * and the synchronizes the current client's service bus state.
332      */
333     void synchronizeRemoteServices();
334 
335     /**
336      * Synchronizes information about the services this client is publishing with the central
337      * service registry.
338      */
339     void synchronizeLocalServices();
340 
341 }