1 /** 2 * Copyright 2005-2013 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.registry; 17 18 import org.kuali.rice.core.api.exception.RiceIllegalArgumentException; 19 import org.kuali.rice.core.api.util.jaxb.QNameAsStringAdapter; 20 import org.kuali.rice.ksb.api.KsbApiConstants; 21 22 import javax.jws.WebMethod; 23 import javax.jws.WebParam; 24 import javax.jws.WebResult; 25 import javax.jws.WebService; 26 import javax.jws.soap.SOAPBinding; 27 import javax.xml.bind.annotation.XmlElement; 28 import javax.xml.bind.annotation.XmlElementWrapper; 29 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 30 import javax.xml.namespace.QName; 31 import java.util.List; 32 33 /** 34 * Defines the interface for a remotely accessible service registry. Applications 35 * can query for information about available services through the apis provided 36 * as well as publishing their own services. 37 * 38 * <p>The {@code ServiceRegistry} deals primarily with the concept of a 39 * {@link ServiceEndpoint} which holds a {@link ServiceInfo} 40 * and a {@link ServiceDescriptor}. These pieces include information about the 41 * service and it's configuration which might be needed by applications wishing to 42 * invoke those services. 43 * 44 * <p>Many of the operations on the {@code ServiceRegistry} only return the 45 * {@code ServiceInfo}. This is because retrieving the full {@code ServiceDescriptor} 46 * is a more expensive operation (since it consists of a serialized XML 47 * representation of the service's configuration which needs to be unmarshaled 48 * and processed) and typically the descriptor is only needed when the client 49 * application actually wants to connect to the service. 50 * 51 * <p>The {@link ServiceInfo} provides two important pieces of information which 52 * help the registry (and the applications which interact with it) understand 53 * who the owner of a service is. The first of these is the "application id" 54 * which identifies the application which owns the service. In terms of 55 * Kuali Rice, an "application" is an abstract concept and consist of multiple 56 * instances of an application which are essentially mirrors of each other and 57 * publish the same set of services. Each of these individuals instances of 58 * an application is identified by the "instance id" which is also available 59 * from the {@code ServiceInfo}. 60 * 61 * @see ServiceEndpoint 62 * @see ServiceInfo 63 * @see ServiceDescriptor 64 * 65 * @author Kuali Rice Team (rice.collab@kuali.org) 66 */ 67 @WebService(name = "serviceRegistry", targetNamespace = KsbApiConstants.Namespaces.KSB_NAMESPACE_2_0) 68 @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL, parameterStyle = SOAPBinding.ParameterStyle.WRAPPED) 69 public interface ServiceRegistry { 70 71 /** 72 * Returns an unmodifiable list of {@link ServiceInfo} for all services that have a status 73 * of {@link ServiceEndpointStatus#ONLINE} with the given name. If there 74 * are no services with the given name, this method should return an empty 75 * list. 76 * 77 * <p>It is typical in clustered environments and other situations that 78 * more than one online service might be available for a given service name. 79 * It is intended that a client of the registry will use an available endpoint 80 * of their choosing to connect to and invoke the service. 81 * 82 * @param serviceName the name of the service to locate 83 * 84 * @return an unmodifiable list of {@code ServiceInfo} for online services with the given name. 85 * If no services were found, an empty list will be returned, but this method should never 86 * return null. 87 * 88 * @throws RiceIllegalArgumentException if serviceName is null 89 */ 90 @WebMethod(operationName = "getOnlineServiceByName") 91 @WebResult(name = "serviceInfos") 92 @XmlElementWrapper(name = "serviceInfos", required = false) 93 @XmlElement(name = "serviceInfo", required = false) 94 List<ServiceInfo> getOnlineServicesByName( 95 @XmlJavaTypeAdapter(QNameAsStringAdapter.class) 96 @WebParam(name = "serviceName") 97 QName serviceName) throws RiceIllegalArgumentException; 98 99 /** 100 * Returns an unmodifiable list of {@link ServiceInfo} for all services in 101 * the registry that have a status of {@link ServiceEndpointStatus#ONLINE}. 102 * If there are no online services in the registry, this method will return 103 * an empty list. 104 * 105 * @return an unmodifiable list of {@code ServiceInfo} for all online services 106 * in the registry. If no services were found, an empty list will be 107 * returned, but this method should never return null. 108 */ 109 @WebMethod(operationName = "getAllOnlineServices") 110 @WebResult(name = "serviceInfo") 111 @XmlElementWrapper(name = "serviceInfos", required = false) 112 @XmlElement(name = "serviceInfo", required = false) 113 List<ServiceInfo> getAllOnlineServices(); 114 115 /** 116 * Returns an unmodifiable list of {@link ServiceInfo} for all services in 117 * the registry. If there are no services in the registry, this method will 118 * return an empty list. 119 * 120 * @return an unmodifiable list of {@code ServiceInfo} for all services in the 121 * registry. If no services were found, an empty list will be returned, but 122 * this method should never return null. 123 */ 124 @WebMethod(operationName = "getAllServices") 125 @WebResult(name = "serviceInfo") 126 @XmlElementWrapper(name = "serviceInfos", required = false) 127 @XmlElement(name = "serviceInfo", required = false) 128 List<ServiceInfo> getAllServices(); 129 130 /** 131 * Returns an unmodifiable list of {@link ServiceInfo} for all services that 132 * have an instance id which matches the given instance id, regardless of 133 * their status. If there are no services published for the given instance, 134 * this method should return an empty list. 135 * 136 * @param instanceId the instance id of the services to locate 137 * 138 * @return an unmodifiable listof {@code ServiceInfo} for all services in the 139 * registry for the given instance id 140 * 141 * @throws RiceIllegalArgumentException if instanceId is a null or blank value 142 */ 143 @WebMethod(operationName = "getAllServicesForInstance") 144 @WebResult(name = "serviceInfos") 145 @XmlElementWrapper(name = "serviceInfos", required = false) 146 @XmlElement(name = "serviceInfo", required = false) 147 List<ServiceInfo> getAllServicesForInstance(@WebParam(name = "instanceId") String instanceId) throws RiceIllegalArgumentException; 148 149 /** 150 * Returns an unmodifiable list of {@link ServiceInfo} for all services that 151 * have an application id which matches the given application id, regardless of 152 * their status. If there are no services published for the given application, 153 * this method should return an empty list. 154 * 155 * @param applicationId the application id of the services to locate 156 * 157 * @return an unmodifiable listof {@code ServiceInfo} for all services in the 158 * registry for the given application id 159 * 160 * @throws RiceIllegalArgumentException if applicationId is a null or blank value 161 */ 162 @WebMethod(operationName = "getAllServicesForApplication") 163 @WebResult(name = "serviceInfos") 164 @XmlElementWrapper(name = "serviceInfos", required = false) 165 @XmlElement(name = "serviceInfo", required = false) 166 List<ServiceInfo> getAllServicesForApplication(@WebParam(name = "applicationId") String applicationId) throws RiceIllegalArgumentException; 167 168 /** 169 * Returns the {@link ServiceDescriptor} which has the given id. If there 170 * is no descriptor for the id, this method will return null. 171 * 172 * @param serviceDescriptorId 173 * @return 174 * @throws RiceIllegalArgumentException 175 */ 176 @WebMethod(operationName = "getServiceDescriptor") 177 @WebResult(name = "serviceDescriptor") 178 @XmlElement(name = "serviceDescriptor", required = false) 179 ServiceDescriptor getServiceDescriptor(@WebParam(name = "serviceDescriptorId") String serviceDescriptorId) throws RiceIllegalArgumentException; 180 181 /** 182 * Returns an unmodifiable list of {@link ServiceDescriptor} which match the 183 * given list of service descriptor ids. The list that is returned from this 184 * method may be smaller than the list of ids that were supplied. This 185 * happens in cases where a service descriptor for a given id in the list 186 * could not be found. 187 * 188 * @param serviceDescriptorIds the list of service descriptor ids for which to 189 * locate the corresponding service descriptor 190 * 191 * @return an unmodifiable list of the service descriptors that could be 192 * located for the given list of ids. This list may be smaller than the 193 * original list of ids that was supplied if the corresponding descriptor 194 * could not be located for a given id in the registry. If no service 195 * descriptors could be located, this method will return an empty list. It 196 * should never return null. 197 * 198 * @throws RiceIllegalArgumentException if serviceDescriptorIds is null 199 */ 200 @WebMethod(operationName = "getServiceDescriptors") 201 @WebResult(name = "serviceDescriptors") 202 @XmlElementWrapper(name = "serviceDescriptors", required = false) 203 @XmlElement(name = "serviceDescriptor", required = false) 204 List<ServiceDescriptor> getServiceDescriptors(@WebParam(name = "serviceDescriptorId") List<String> serviceDescriptorIds) throws RiceIllegalArgumentException; 205 206 /** 207 * Publishes the given {@link ServiceEndpoint} to the registry. If there 208 * is no service id on the {@code ServiceInfo} then this constitutes a new 209 * registry endpoint, so it will be added to the registry. If the given 210 * endpoint already has a {@code ServiceInfo} with a service id, then the 211 * corresponding entry in the registry will be updated instead. 212 * 213 * @param serviceEndpoint the service endpoint to publish 214 * 215 * @return the result of publishing the endpoint, if this is a new registry 216 * entry, then the service endpoint that is returned will contain access to 217 * both the service id and service descriptor id that were generated for 218 * this entry in the registry. This method will never return null. 219 * 220 * @throws RiceIllegalArgumentException if serviceEndpoint is null 221 */ 222 @WebMethod(operationName = "publishService") 223 @WebResult(name = "serviceEndpoint") 224 @XmlElement(name = "serviceEndpoint", required = true) 225 ServiceEndpoint publishService(@WebParam(name = "serviceEndpoint") ServiceEndpoint serviceEndpoint) throws RiceIllegalArgumentException; 226 227 /** 228 * Publishes the list of {@link ServiceEndpoint}s to the registry. This 229 * functions the same way as executing {@link #publishService(ServiceEndpoint)} 230 * on each individual {@code ServiceEndpoint}. However, it performs this as 231 * an atomic operation, so if there is an error when publishing one service 232 * endpoint in the list, then none of the endpoints will be published. 233 * 234 * @param serviceEndpoints the list of service endpoints to publish 235 * 236 * @return the result of publishing the endpoints (see {@link #publishService(ServiceEndpoint)} 237 * for details). This list will always be the same size and in the same 238 * order as the list of service endpoints that were supplied for publshing. 239 * 240 * @throws RiceIllegalArgumentException if serviceEndpoints is null or if any 241 * {@code ServiceEndpoint} within the list is null 242 */ 243 @WebMethod(operationName = "publishServices") 244 @WebResult(name = "serviceEndpoints") 245 @XmlElementWrapper(name = "serviceEndpoints", required = false) 246 @XmlElement(name = "serviceEndpoint", required = false) 247 List<ServiceEndpoint> publishServices(@WebParam(name = "serviceEndpoint") List<ServiceEndpoint> serviceEndpoints) throws RiceIllegalArgumentException; 248 249 /** 250 * Removes the service from the registry with the given service id if it 251 * exists. If the service with the given id exists and was successfully 252 * removed, a copy of the removed {@link ServiceEndpoint} entry will be 253 * returned. Otherwise, this method will return null. 254 * 255 * @param serviceId the id of the service to remove 256 * 257 * @return the removed {@link ServiceEndpoint} if a service with the given 258 * id exists in the registry, if no such service exists, this method will 259 * return null 260 * 261 * @throws RiceIllegalArgumentException if serviceId is null or a blank value 262 */ 263 @WebMethod(operationName = "removeServiceEndpoint") 264 @WebResult(name = "serviceEndpoint") 265 @XmlElement(name = "serviceEndpoint", required = false) 266 ServiceEndpoint removeServiceEndpoint(@WebParam(name = "serviceId") String serviceId) throws RiceIllegalArgumentException; 267 268 /** 269 * As {@link #removeServiceEndpoint(String)} but removes all services that 270 * match the given list of service ids. It could be the case that some of 271 * the given ids do not match a service in the registry, in this case that 272 * {@link ServiceEndpoint} would not be included in the resulting list of 273 * services that were removed. Because of this, the list that is returned 274 * from this method may be smaller then the list of ids that were supplied. 275 * 276 * @param serviceIds the list of service ids to remove from the registry 277 * 278 * @return a list of all service endpoints that were successfully removed, 279 * if no such endpoints were removed, this list will be empty, but it will 280 * never be null 281 * 282 * @throws RiceIllegalArgumentException if serviceIds is null or if one of 283 * the ids in the list is null or blank 284 */ 285 @WebMethod(operationName = "removeServiceEndpoints") 286 @WebResult(name = "serviceEndpoints") 287 @XmlElementWrapper(name = "serviceEndpoints", required = false) 288 @XmlElement(name = "serviceEndpoint", required = false) 289 List<ServiceEndpoint> removeServiceEndpoints(@WebParam(name = "serviceId") List<String> serviceIds) throws RiceIllegalArgumentException; 290 291 /** 292 * Performs a single atomic operation of removing and publishing a set of 293 * services in the registry. This operation is useful in situations where 294 * a client application contains apis to manage the services they are 295 * publishing on the bus and they want to ensure the registry is kept in 296 * a consistent state in terms of what they have published. 297 * 298 * <p>Behaviorally, this operation is equivalent to performing a 299 * {@link #removeServiceEndpoints(List)} followed by a 300 * {@link #publishServices(List)}, except that a null list is valid for 301 * either {@code removeServiceIds} or {@code publishServiceEndpoints}. In 302 * the case that a null or empty list is passed for either of these, that 303 * particular portion of the operation will not be performed. 304 * 305 * <p>This method returns a {@link RemoveAndPublishResult} which contains 306 * a list of the services that were successfully removed as well as those 307 * that were published. 308 * 309 * @param removeServiceIds the list of ids of the services to remove, if 310 * this parameter is null or an empty list, then no remove operation will 311 * be executed 312 * @param publishServiceEndpoints the list of service endpoints to publish, 313 * if this parameter is null or an empty list, then no publish operation 314 * will be executed 315 * 316 * @return the result of the operation which contains information on which 317 * services were successfully removed as well as published, this method will 318 * never return null 319 */ 320 @WebMethod(operationName = "removeAndPublish") 321 @WebResult(name = "removeAndPublishResult") 322 @XmlElement(name = "removeAndPublishResult", required = true) 323 RemoveAndPublishResult removeAndPublish(@WebParam(name = "removeServiceId") List<String> removeServiceIds, 324 @WebParam(name = "publishServiceEndpoint") List<ServiceEndpoint> publishServiceEndpoints); 325 326 /** 327 * Updates the status for the service with the given id to the given 328 * {@link ServiceEndpointStatus}. 329 * 330 * @param serviceId the id of the service for which to update the status 331 * @param status the status to update this service to 332 * 333 * @return true if the service with the given id exists in the registry and 334 * was updated, false otherwise 335 * 336 * @throws RiceIllegalArgumentException if serviceId is null or a blank value 337 * @throws RiceIllegalArgumentException if status is null 338 */ 339 @WebMethod(operationName = "updateStatus") 340 @WebResult(name = "statusUpdated") 341 boolean updateStatus(@WebParam(name = "serviceId") String serviceId, @WebParam(name = "status") ServiceEndpointStatus status) throws RiceIllegalArgumentException; 342 343 /** 344 * As per {@link #updateStatus(String, ServiceEndpointStatus)} but updates 345 * mutliple statuses as part of a single operation. 346 * 347 * <p>This method returns a List of ids of the services that were updated. 348 * If a given service id does not exist in the registry, that id won't be 349 * included in the result. So the resuling list of updated ids may be 350 * smaller than the given list of service ids (though it will never be 351 * null). 352 * 353 * @param serviceIds the list of ids of the services for which to update the status 354 * @param status the status to update the services to 355 * 356 * @return an unmodifiable list containing the ids of the services that 357 * were successfully updated, since it's possible some of the supplied ids 358 * might not exist in the registry this list could be smaller than the 359 * given serviceIds list 360 * 361 * @throws RiceIllegalArgumentException if serviceIds is null or if any of 362 * the entries in the list is null or has a blank value 363 * @throws RiceIllegalArgumentException if status is null 364 */ 365 @WebMethod(operationName = "updateStatuses") 366 @WebResult(name = "serviceIds") 367 @XmlElementWrapper(name = "serviceIds", required = false) 368 @XmlElement(name = "serviceId", required = false) 369 List<String> updateStatuses(@WebParam(name = "serviceId") List<String> serviceIds, @WebParam(name = "status") ServiceEndpointStatus status) throws RiceIllegalArgumentException; 370 371 /** 372 * Flips the status of all services that match the given instance id to the 373 * status of {@link ServiceEndpointStatus#OFFLINE. It is intended that this 374 * operation will be used by a registry client who is going offline for 375 * maintenance or other reasons and wants to ensure that the state of the 376 * registry is consistent with the application's state. 377 * 378 * @param instanceId the id of the instance for which to set all services to 379 * the offline status 380 * 381 * @throws RiceIllegalArgumentException if instanceId is null or a blank value 382 */ 383 @WebMethod(operationName = "takeInstanceOffline") 384 void takeInstanceOffline(@WebParam(name = "instanceId") String instanceId) throws RiceIllegalArgumentException; 385 386 }