[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]
Subject: Java Callback Simplification Proposal
All, Bellow is a proposal from BEA to simplify callback mechanisms in the Java C&I specifications. I will work on the appropriate steps of getting this into a JIRA so that it can be tracked. Thanks, Jim This proposal aims to simplify using asynchronous communication in the SCA Java programming model by: 1. Eliminating callback objects. - Removing ServiceReference.get/setCallback() 2. Removing the ability for service providers to get callback IDs. - Moving CallableReference getCallbackID() to ServiceReference) 3. Saying callback IDs are irrelevant in conversations. - Making ServiceReference.setCallbackID(Object id) illegal and ServiceReference.getCallbackID() (assuming #2) return null for conversational interactions. 4. Removing the distinction between stateless and conversational callback interfaces. - Removing the ability to specify conversational on callback Interfaces. By simplification, we mean as a primarily reducing the number of concepts and APIs a developer must understand to program asynchronous services. This will entail some reduction in capability. However, this reduction, we argue, affects edge-cases that can be accommodated through alternative techniques. A secondary aspect of simplification concerns implementation. By removing the requirement for runtimes to provide infrastructure for handling edge cases that can be accommodated through relatively simple application programming techniques,implementing callback capabilities becomes fairly straightforward. [RATIONAL] The rational for proposed items is dealt with individually in this section. 1. ServiceReference.setCallback(Object object) and ServiceReference.getCallback() ------------------------------------------------------------------------ --------------------------------------------- This API exists as a mechanism to route callbacks to instances other than an instance of the client component making a forward invocation. This provides two capabilities. Clients do not have to implement a callback interface. The API also allows clients to instruct the runtime to perform callback dispatching for stateless interactions that execute concurrently. A common example of this is inventory check. A client component needs to perform an inventory check for multiple line items. As an efficiency, it written to invoke the same inventory service using a non-blocking call multiple times. For each invocation, it wishes to dispatch the associated callback to a different handler instance it creates. For example: ServiceReference<InventoryService> serviceReference = .. for (LineItem item: purchaseOrder.getLineItems()) { CallbackService handler = new CallbackServiceImpl(); serviceReference.setCallback(handler) serviceReference.getService().checkInventory(item); } This can be done using the CallableReference.getCallbackID(): // code that conducts the forward invoke: ServiceReference<InventoryService> serviceReference = .. for (LineItem item: purchaseOrder.getLineItems()) { String id = // generate or assign the callback ID // store the callback id and whatever information the callback needs cache.put(id, handler); serviceReference.getService().checkInventory(item); } Callback processing can either be done directly by a component implementation instance or delegated to CallbackServiceImpl as shown below: // code in the same class that handles the callback: public void onCallback(InventoryStatus status) { String id = requestContext.getServiceReference().getCallbackID(); CallbackInfo info = .. // retrieve the stored callback information by using the callback id CallbackService handler = new CallbackServiceImpl(info); handler.onCallback(status); } Some advantages to eliminating get/set/Callback() are: a. Reduces the number of concepts and APIs a developer will be presented with without affecting common functionality. In other words, this API is primarily used for edge-cases and removing it simplifies the common case. b. Application migrations and versioning are easier using the alternative approach. By using an object instance, runtime implementations would be responsible for handling class versioning for in-process interactions. By avoiding serialization and the use of a specific classes, and instead storing callback data, CallbackServiceImpl can be versioned and substituted for callbacks that have not yet occurred. c. Runtime performance characteristics are likely to improve. For cases where the client is stateless, routing to the specific instance set through setCallback() requires that the callback be routed to the specific JVM where the instance is hosted. Eliminating routing to a particular instance allows the callback to potentially be sent to any JVM where the client component is hosted. d. Eliminates the need for runtime implementations to manage garbage collection of callback objects. For example, if a callback is never made, the runtime at some point will need to remove the object from storage or memory. 2. Moving CallableReference.getCallbackID() to ServiceReference ------------------------------------------------------------------------ -------------------- We propose removing getCallbackID() from access by service providers as it is cannot be used for correlation in third-party components except when the third-party is configured with a callback to the same client component. For example in the stateless case: A---------B--------C The only way C can callback to A is either by calling back B or having B pass a CallableReference to C. The callback ID is not sufficient, in itself, to be used by arbitrary code to send a message that qualifies as a callback in this bidirectional exchange. For example, if B has clients other than A, the callback ID doesn’t have the information to tell which client it is for. Moving CallableReference.getCallbackID() to ServiceReference simplifies the Java programming model by: a. Eliminating an API that can only be used in very particular circumstances. b. Removing the need for a runtime implementation to create and maintain a distributed domain-wide mapping of callback ids to callback endpoints. Note that routing information cannot be encoded in the callback id as it can be set by the application. 3. Making ServiceReference.setCallbackID(Object id) illegal and ServiceReference.getCallbackID() (assuming #2) return null for conversational interactions. ------------------------------------------------------------------------ ------------------------------------------------------------------------ ---------------------------------------------------------------------- Having both callback ids and conversation ids for bi-directional conversational wires is confusing and not needed as the conversation id will be used for correlation. Sometimes a client may wish to correlate callback invocations using the callback id. For conversational callbacks, correlation using the callback id is limited. Since conversations are serial between a particular client instance and a provider instance, the additional correlation that may be needed is between different invocations to the provider within the same conversation. In other words, conversations by nature correlate invocations between a client and provider instance. If finer-grained correlation is needed such as between multiple invocations in the same conversation, correlation data can be included as part of the service operation data (e.g. “line item number” can be passed as a parameter in the example above). This simplifies the Java programming model by clarifying the relationship between callback and conversation ids. 4. Removing the ability to specify stateless or conversational callback service contracts ------------------------------------------------------------------------ ----------------------------------------------------- We propose wires be either conversational or stateless in both directions and that it be specified as part of the forward service contract. In other words, @Conversational cannot be specified on the callback interface definition. We don't believe having a stateless callback for a stateful forward invocation and vice versa makes much sense.
[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]