1 /** 2 * Copyright 2005-2012 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 remotely accessible endpoints that are available in the 78 * service registry with the given service name. This method will only return endpoints that the 79 * service bus believes are online, endpoints which are offline will not be included. 80 * 81 * <p> 82 * If the service bus client has also deployed a service with this name, a remoted endpoint to 83 * this service will likely also be included in this list assuming that endpoint has already 84 * been synchronized with the registry. 85 * 86 * <p> 87 * In most cases, it is preferable to use {@link #getEndpoints(QName)} instead of this method. 88 * Because it will preferably return a local endpoint reference for a given service endpoint if 89 * one is available. 90 * 91 * @return a list of all endpoints that are available for the given service name, this list will 92 * never be null but may be empty if there are no endpoints for the given service name 93 * @throws IllegalArgumentException if serviceName is null 94 */ 95 List<Endpoint> getRemoteEndpoints(QName serviceName); 96 97 /** 98 * Returns the endpoint for the service with the given name that was published by this service 99 * bus client. If this client has not published any such service, then this method will return 100 * null. 101 * 102 * @param serviceName the name of the service represented by the local endpoint 103 * @return the local endpoint for the given service name which was deployed by this client, or 104 * null if no such service has been published 105 * @throws IllegalArgumentException if serviceName is null 106 */ 107 Endpoint getLocalEndpoint(QName serviceName); 108 109 /** 110 * Returns an unmodifiable list of all services that have been published by this service bus 111 * client. 112 * 113 * @return a map with the local service name as the key and the local endpoint as the value 114 * which contains all local services published by this service bus client. This map may 115 * be empty if this client has published no services, but it should never be null. 116 */ 117 Map<QName, Endpoint> getLocalEndpoints(); 118 119 /** 120 * Returns an unmodifiable list of all available and online endpoints of which the service bus 121 * is aware, including both local and remote endpoints. 122 * 123 * @return all available endpoints, this list may be empty if no endpoints exist but will never 124 * be null 125 */ 126 List<Endpoint> getAllEndpoints(); 127 128 /** 129 * Returns an available endpoint for the service with the given name. If the service with the 130 * given name is published locally, preference will be given to the locally deployed version of 131 * the service. 132 * 133 * <p> 134 * Based on the nature of this method, if there is more than one endpoint available for the 135 * given name, multiple invocations of this method with the same service name may return 136 * different {@link Endpoint} instances each time. 137 * 138 * @param serviceName the name of the service for which to locate an available endpoint 139 * @return an available endpoint for the service with the given name, or null if none is 140 * available 141 * @throws IllegalArgumentException if serviceName is null 142 */ 143 Endpoint getEndpoint(QName serviceName); 144 145 /** 146 * Returns an available endpoint for the service with the given name which is hosted by the 147 * application with the given application id. This operation functions the same as 148 * {@link #getEndpoint(QName)} with the exception that it will only consider endpoints with the 149 * given application id. 150 * 151 * <p> 152 * Invoking this method with a null or blank value for {@code applicationId} is equivalent to 153 * invoking {@link #getEndpoint(QName)}. 154 * 155 * @param serviceName the name of the service for which to locate an available endpoint 156 * @param applicationId the id of the application for which to locate an available endpoint for 157 * the given service name 158 * @return an available endpoint for the service with the given name and application id, or null 159 * if none is available 160 * @throws IllegalArgumentException if serviceName is null 161 */ 162 Endpoint getEndpoint(QName serviceName, String applicationId); 163 164 /** 165 * Returns the endpoint matching the given service configuration, if one exists. In the case of 166 * services published by this service bus client, this method will preferably return the local 167 * endpoints in place of a remote endpoint to the same service. 168 * 169 * @param serviceConfiguration the service configuration by which to lookup up the endpoint 170 * @return the endpoint who's service configuration matches the given configuration, or null if 171 * no such match could be determined 172 * @throws IllegalArgumentException if the given serviceConfiguration is null 173 */ 174 Endpoint getConfiguredEndpoint(ServiceConfiguration serviceConfiguration); 175 176 /** 177 * Returns a proxy to the service with the given name. This proxy should have built-in support 178 * for fail-over and load balancing capabilities. This means it is safe for client applications 179 * to cache a reference to this service proxy. 180 * 181 * <p> 182 * This proxy should additionally be thread-safe. 183 * 184 * <p> 185 * This method is equivalent to invoking {@link #getEndpoint(QName).getService()}. 186 * 187 * @param serviceName the name of the service for which to locate an available proxy 188 * @return an available proxy for the service with the given name, or null if none is available 189 * @throws IllegalArgumentException if serviceName is null 190 */ 191 Object getService(QName serviceName); 192 193 /** 194 * Returns a proxy to the service with the given name which is hosted by the application with 195 * the given application id. This operation functions the same as {@link #getService(QName)} 196 * with the exception that it will only consider endpoints with the given application id. 197 * 198 * <p> 199 * Invoking this method with a null or blank value for {@code applicationId} is equivalent to 200 * invoking {@link #getService(QName)}. This method is also equivalent to invoking 201 * {@link #getEndpoint(QName, String).getService()}. 202 * 203 * @param serviceName the name of the service for which to locate an available proxy 204 * @param applicationId the id of the application for which to locate an available proxy for the 205 * given service name 206 * @return an available proxy for the service with the given name, or null if none is available 207 * @throws IllegalArgumentException if serviceName is null 208 */ 209 Object getService(QName serviceName, String applicationId); 210 211 /** 212 * Publish a service with the given ServiceDefinition to the service bus. This effectively 213 * updates the service registry and provides an endpoint for other applications to invoke. If 214 * this application has already published a service under this name, it will be updated instead 215 * to reflect the new ServiceDefinition. 216 * 217 * <p> 218 * The method also provides the ability for the service bus to immediately synchronize with the 219 * service registry after registering the service if {@code synchronize} is set to {@code true}. 220 * 221 * @see #synchronize() 222 * 223 * @param serviceDefinition the definition of the service to publish, must not be null 224 * @param synchronize indicates whether or not this service bus client should immediately 225 * synchronize it's changes with the registry after registering the service. 226 * @return the service configuration for the published service 227 * @throws IllegalArgumentException if serviceDefinition is null 228 */ 229 ServiceConfiguration publishService(ServiceDefinition serviceDefinition, boolean synchronize); 230 231 /** 232 * Functions as per {@link #publishService(ServiceDefinition, boolean)} but allows for multiple 233 * services to be published to the bus in a single operation. If the given list of service 234 * definitions is empty then this method will do nothing (including skipping synchronization 235 * with the registry if that was requested). 236 * 237 * @see #publishService(ServiceDefinition, boolean) 238 * @see #synchronize() 239 * 240 * @param serviceDefinitions the list of definition for the services to publish, must not be 241 * null 242 * @param synchronize indicates whether or not this service bus client should immediately 243 * synchronize it's changes with the registry after registering the services. 244 * @return the list of service configurations for the published services in the same order as 245 * the list of service definitions 246 * @throws IllegalArgumentException if serviceDefinitions is null 247 */ 248 List<ServiceConfiguration> publishServices(List<ServiceDefinition> serviceDefinitions, boolean synchronize); 249 250 /** 251 * Removes the service from the service bus and the service registry with the given service 252 * name. Client applications should only be able to remove services that they themselves have 253 * published. 254 * 255 * <p> 256 * This method also provides the ability for the service bus to immediately synchronize with the 257 * service registry after removing the service if {@code synchronize} is set to {@code true}. If 258 * the service is not located and successfully removed, however, the sychronization will not 259 * run. 260 * 261 * @see #synchronize() 262 * 263 * @param serviceName the name of the service to remove 264 * @param synchronize indicates whether or not this service bus client should immediately 265 * synchronize after removing the service 266 * @return true if the service was removed, false otherwise 267 * @throws IllegalArgumentException if the given serviceName is null 268 */ 269 boolean removeService(QName serviceName, boolean synchronize); 270 271 /** 272 * Functions as per {@link #removeService(QName, boolean)} but allows for multiple services to 273 * be removed from the bus in a single operation. If the given list of service names is empty 274 * then this method will do nothing (including skipping synchronization with the registry if 275 * that was requested). 276 * 277 * <p> 278 * If the list returned from the method contains only false responses (meaning that no services 279 * were removed) this method will skip synchronization even if it is requested. 280 * 281 * @see #removeService(QName, boolean) 282 * @see #synchronize() 283 * 284 * @param serviceNames the list of names for the services to remove, must not be null 285 * @param synchronize indicates whether or not this service bus client should immediately 286 * synchronize it's changes with the registry after removing the services. 287 * @return a list of Booleans indicating which of the service removals were successful. This 288 * list will be in the same order as the list of service configurations that were passed 289 * in. 290 * @throws IllegalArgumentException if serviceNames is null 291 */ 292 List<Boolean> removeServices(List<QName> serviceNames, boolean synchronize); 293 294 /** 295 * Synchronizes the current client's service bus with the central service registry. This may be 296 * done automatically on a periodic basic depending on the implementation of this service, but 297 * can be invoked manually through this method. This method should both register any outstanding 298 * service publications to the registry, as well as detect any changes in remote services that 299 * have been published/removed by other applications in the registry and update local service 300 * bus state accordingly. 301 * 302 * <p>Invoking this method is equivalent to invoking {@link #synchronizeLocalServices()} and 303 * {@link #synchronizeRemoteServices()} in either order. However, the semantics vary slightly 304 * as this method should attempt to invoke them as an atomic operation.</p> 305 */ 306 void synchronize(); 307 308 /** 309 * Fetches information about the current state of the remote services available in the registry 310 * and the synchronizes the current client's service bus state. 311 */ 312 void synchronizeRemoteServices(); 313 314 /** 315 * Synchronizes information about the services this client is publishing with the central 316 * service registry. 317 */ 318 void synchronizeLocalServices(); 319 320 }