1 /**
2 * Copyright 2005-2015 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 }