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.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 the {@link ServiceDescriptor} which has the given id. If there 151 * is no descriptor for the id, this method will return null. 152 * 153 * @param serviceDescriptorId 154 * @return 155 * @throws RiceIllegalArgumentException 156 */ 157 @WebMethod(operationName = "getServiceDescriptor") 158 @WebResult(name = "serviceDescriptor") 159 @XmlElement(name = "serviceDescriptor", required = false) 160 ServiceDescriptor getServiceDescriptor(@WebParam(name = "serviceDescriptorId") String serviceDescriptorId) throws RiceIllegalArgumentException; 161 162 /** 163 * Returns an unmodifiable list of {@link ServiceDescriptor} which match the 164 * given list of service descriptor ids. The list that is returned from this 165 * method may be smaller than the list of ids that were supplied. This 166 * happens in cases where a service descriptor for a given id in the list 167 * could not be found. 168 * 169 * @param serviceDescriptorIds the list of service descriptor ids for which to 170 * locate the corresponding service descriptor 171 * 172 * @return an unmodifiable list of the service descriptors that could be 173 * located for the given list of ids. This list may be smaller than the 174 * original list of ids that was supplied if the corresponding descriptor 175 * could not be located for a given id in the registry. If no service 176 * descriptors could be located, this method will return an empty list. It 177 * should never return null. 178 * 179 * @throws RiceIllegalArgumentException if serviceDescriptorIds is null 180 */ 181 @WebMethod(operationName = "getServiceDescriptors") 182 @WebResult(name = "serviceDescriptors") 183 @XmlElementWrapper(name = "serviceDescriptors", required = false) 184 @XmlElement(name = "serviceDescriptor", required = false) 185 List<ServiceDescriptor> getServiceDescriptors(@WebParam(name = "serviceDescriptorId") List<String> serviceDescriptorIds) throws RiceIllegalArgumentException; 186 187 /** 188 * Publishes the given {@link ServiceEndpoint} to the registry. If there 189 * is no service id on the {@code ServiceInfo} then this constitutes a new 190 * registry endpoint, so it will be added to the registry. If the given 191 * endpoint already has a {@code ServiceInfo} with a service id, then the 192 * corresponding entry in the registry will be updated instead. 193 * 194 * @param serviceEndpoint the service endpoint to publish 195 * 196 * @return the result of publishing the endpoint, if this is a new registry 197 * entry, then the service endpoint that is returned will contain access to 198 * both the service id and service descriptor id that were generated for 199 * this entry in the registry. This method will never return null. 200 * 201 * @throws RiceIllegalArgumentException if serviceEndpoint is null 202 */ 203 @WebMethod(operationName = "publishService") 204 @WebResult(name = "serviceEndpoint") 205 @XmlElement(name = "serviceEndpoint", required = true) 206 ServiceEndpoint publishService(@WebParam(name = "serviceEndpoint") ServiceEndpoint serviceEndpoint) throws RiceIllegalArgumentException; 207 208 /** 209 * Publishes the list of {@link ServiceEndpoint}s to the registry. This 210 * functions the same way as executing {@link #publishService(ServiceEndpoint)} 211 * on each individual {@code ServiceEndpoint}. However, it performs this as 212 * an atomic operation, so if there is an error when publishing one service 213 * endpoint in the list, then none of the endpoints will be published. 214 * 215 * @param serviceEndpoints the list of service endpoints to publish 216 * 217 * @return the result of publishing the endpoints (see {@link #publishService(ServiceEndpoint)} 218 * for details). This list will always be the same size and in the same 219 * order as the list of service endpoints that were supplied for publshing. 220 * 221 * @throws RiceIllegalArgumentException if serviceEndpoints is null or if any 222 * {@code ServiceEndpoint} within the list is null 223 */ 224 @WebMethod(operationName = "publishServices") 225 @WebResult(name = "serviceEndpoints") 226 @XmlElementWrapper(name = "serviceEndpoints", required = false) 227 @XmlElement(name = "serviceEndpoint", required = false) 228 List<ServiceEndpoint> publishServices(@WebParam(name = "serviceEndpoint") List<ServiceEndpoint> serviceEndpoints) throws RiceIllegalArgumentException; 229 230 /** 231 * Removes the service from the registry with the given service id if it 232 * exists. If the service with the given id exists and was successfully 233 * removed, a copy of the removed {@link ServiceEndpoint} entry will be 234 * returned. Otherwise, this method will return null. 235 * 236 * @param serviceId the id of the service to remove 237 * 238 * @return the removed {@link ServiceEndpoint} if a service with the given 239 * id exists in the registry, if no such service exists, this method will 240 * return null 241 * 242 * @throws RiceIllegalArgumentException if serviceId is null or a blank value 243 */ 244 @WebMethod(operationName = "removeServiceEndpoint") 245 @WebResult(name = "serviceEndpoint") 246 @XmlElement(name = "serviceEndpoint", required = false) 247 ServiceEndpoint removeServiceEndpoint(@WebParam(name = "serviceId") String serviceId) throws RiceIllegalArgumentException; 248 249 /** 250 * As {@link #removeServiceEndpoint(String)} but removes all services that 251 * match the given list of service ids. It could be the case that some of 252 * the given ids do not match a service in the registry, in this case that 253 * {@link ServiceEndpoint} would not be included in the resulting list of 254 * services that were removed. Because of this, the list that is returned 255 * from this method may be smaller then the list of ids that were supplied. 256 * 257 * @param serviceIds the list of service ids to remove from the registry 258 * 259 * @return a list of all service endpoints that were successfully removed, 260 * if no such endpoints were removed, this list will be empty, but it will 261 * never be null 262 * 263 * @throws RiceIllegalArgumentException if serviceIds is null or if one of 264 * the ids in the list is null or blank 265 */ 266 @WebMethod(operationName = "removeServiceEndpoints") 267 @WebResult(name = "serviceEndpoints") 268 @XmlElementWrapper(name = "serviceEndpoints", required = false) 269 @XmlElement(name = "serviceEndpoint", required = false) 270 List<ServiceEndpoint> removeServiceEndpoints(@WebParam(name = "serviceId") List<String> serviceIds) throws RiceIllegalArgumentException; 271 272 /** 273 * Performs a single atomic operation of removing and publishing a set of 274 * services in the registry. This operation is useful in situations where 275 * a client application contains apis to manage the services they are 276 * publishing on the bus and they want to ensure the registry is kept in 277 * a consistent state in terms of what they have published. 278 * 279 * <p>Behaviorally, this operation is equivalent to performing a 280 * {@link #removeServiceEndpoints(List)} followed by a 281 * {@link #publishServices(List)}, except that a null list is valid for 282 * either {@code removeServiceIds} or {@code publishServiceEndpoints}. In 283 * the case that a null or empty list is passed for either of these, that 284 * particular portion of the operation will not be performed. 285 * 286 * <p>This method returns a {@link RemoveAndPublishResult} which contains 287 * a list of the services that were successfully removed as well as those 288 * that were published. 289 * 290 * @param removeServiceIds the list of ids of the services to remove, if 291 * this parameter is null or an empty list, then no remove operation will 292 * be executed 293 * @param publishServiceEndpoints the list of service endpoints to publish, 294 * if this parameter is null or an empty list, then no publish operation 295 * will be executed 296 * 297 * @return the result of the operation which contains information on which 298 * services were successfully removed as well as published, this method will 299 * never return null 300 */ 301 @WebMethod(operationName = "removeAndPublish") 302 @WebResult(name = "removeAndPublishResult") 303 @XmlElement(name = "removeAndPublishResult", required = true) 304 RemoveAndPublishResult removeAndPublish(@WebParam(name = "removeServiceId") List<String> removeServiceIds, 305 @WebParam(name = "publishServiceEndpoint") List<ServiceEndpoint> publishServiceEndpoints); 306 307 /** 308 * Updates the status for the service with the given id to the given 309 * {@link ServiceEndpointStatus}. 310 * 311 * @param serviceId the id of the service for which to update the status 312 * @param status the status to update this service to 313 * 314 * @return true if the service with the given id exists in the registry and 315 * was updated, false otherwise 316 * 317 * @throws RiceIllegalArgumentException if serviceId is null or a blank value 318 * @throws RiceIllegalArgumentException if status is null 319 */ 320 @WebMethod(operationName = "updateStatus") 321 @WebResult(name = "statusUpdated") 322 boolean updateStatus(@WebParam(name = "serviceId") String serviceId, @WebParam(name = "status") ServiceEndpointStatus status) throws RiceIllegalArgumentException; 323 324 /** 325 * As per {@link #updateStatus(String, ServiceEndpointStatus)} but updates 326 * mutliple statuses as part of a single operation. 327 * 328 * <p>This method returns a List of ids of the services that were updated. 329 * If a given service id does not exist in the registry, that id won't be 330 * included in the result. So the resuling list of updated ids may be 331 * smaller than the given list of service ids (though it will never be 332 * null). 333 * 334 * @param serviceIds the list of ids of the services for which to update the status 335 * @param status the status to update the services to 336 * 337 * @return an unmodifiable list containing the ids of the services that 338 * were successfully updated, since it's possible some of the supplied ids 339 * might not exist in the registry this list could be smaller than the 340 * given serviceIds list 341 * 342 * @throws RiceIllegalArgumentException if serviceIds is null or if any of 343 * the entries in the list is null or has a blank value 344 * @throws RiceIllegalArgumentException if status is null 345 */ 346 @WebMethod(operationName = "updateStatuses") 347 @WebResult(name = "serviceIds") 348 @XmlElementWrapper(name = "serviceIds", required = false) 349 @XmlElement(name = "serviceId", required = false) 350 List<String> updateStatuses(@WebParam(name = "serviceId") List<String> serviceIds, @WebParam(name = "status") ServiceEndpointStatus status) throws RiceIllegalArgumentException; 351 352 /** 353 * Flips the status of all services that match the given instance id to the 354 * status of {@link ServiceEndpointStatus#OFFLINE. It is intended that this 355 * operation will be used by a registry client who is going offline for 356 * maintenance or other reasons and wants to ensure that the state of the 357 * registry is consistent with the application's state. 358 * 359 * @param instanceId the id of the instance for which to set all services to 360 * the offline status 361 * 362 * @throws RiceIllegalArgumentException if instanceId is null or a blank value 363 */ 364 @WebMethod(operationName = "takeInstanceOffline") 365 void takeInstanceOffline(@WebParam(name = "instanceId") String instanceId) throws RiceIllegalArgumentException; 366 367 }