Author: timothyjward
Date: Thu Jul  2 15:39:22 2015
New Revision: 1688849

URL: http://svn.apache.org/r1688849
Log:
Documentation for the Async Service

Modified:
    aries/site/trunk/content/modules/async-svcs.mdtext   (contents, props 
changed)

Modified: aries/site/trunk/content/modules/async-svcs.mdtext
URL: 
http://svn.apache.org/viewvc/aries/site/trunk/content/modules/async-svcs.mdtext?rev=1688849&r1=1688848&r2=1688849&view=diff
==============================================================================
--- aries/site/trunk/content/modules/async-svcs.mdtext (original)
+++ aries/site/trunk/content/modules/async-svcs.mdtext Thu Jul  2 15:39:22 2015
@@ -1,6 +1,160 @@
+Title:
+Notice:    Licensed to the Apache Software Foundation (ASF) under one
+           or more contributor license agreements.  See the NOTICE file
+           distributed with this work for additional information
+           regarding copyright ownership.  The ASF licenses this file
+           to you under the Apache License, Version 2.0 (the
+           "License"); you may not use this file except in compliance
+           with the License.  You may obtain a copy of the License at
+           .
+             http://www.apache.org/licenses/LICENSE-2.0
+           .
+           Unless required by applicable law or agreed to in writing,
+           software distributed under the License is distributed on an
+           "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+           KIND, either express or implied.  See the License for the
+           specific language governing permissions and limitations
+           under the License.
+
 Title: Asynchronous Services
 
-#OSGi Asynchronous Services
+#Introduction
+The R6 OSGi specifications include support for Asynchronous programming using 
OSGi services. 
+Apache Aries aims to provide small, compliant implementations of these 
specifications to enable asynchronous
+programming in enterprise applications. The two key specifications are OSGi 
Promises and the Async service.
+
+#OSGi Promises
+
+One of the fundamental pieces of an asynchronous programming system is the 
*Promise*. A Promise is a holder type that 
+represents an asynchronous calcluation. Since Java 5 the JDK has contained 
*java.util.concurrent.Future* to perform this 
+function. Java's Future type is, however, fatally flawed as it has no callback 
to notify the user when it resolves. Instead the
+user must make a blocking call to *get()*.
+
+OSGi promises fix this problem by defining a Promise interface which allows 
the user to register callbacks which will be
+called when the promise *resolves*. These callbacks are lambda friendly SAM 
types, but the Promise API itself has no
+dependencies on Java 8. The Aries version (org.apache.aries.async.promise.api) 
has a minimum requirement of JDK 6.
+
+##Creating OSGi Promises
+
+Creating a Promise is easy. The *org.osgi.util.promise.Deferred* type is a 
factory for a single promise, and can also be used to
+resolve or fail the promise:
+
+       Deferred<Integer> deferred = new Deferred<>();
+       new Thread(() -> {
+                       int result = calculateReallyHardSum();
+                       deferred.resolve(result);
+               }).start();
+       
+       Promise<Integer> p = deferred.getPromise();
+       ...
+
+But wait - what if something goes wrong? How do we signal to the user that 
there was a problem and the result is never coming?
+The answer is very easy - Promises have the concept of *failure*. A promise 
will *either* resolve *or* fail at most once. For well 
+written code this rule is usually the same as "A promise will either resolve 
or fail *exactly* once". Promises are thread safe and
+effectively immutable, meaning they can be shared with other code.
+
+       Deferred<Integer> deferred = new Deferred<>();
+       new Thread(() -> {
+                       try {
+                               int result = calculateErrorProneSum();
+                               deferred.resolve(result);
+                       } catch (Exception e) {
+                               deferred.fail(e);
+                       }
+               }).start();
+       
+       Promise<Integer> p = deferred.getPromise();
+       ...
+
+##Using OSGi Promises
+
+Once you have a promise, what do you do with it? It's easy to get the value 
from a promise using the *getValue()* method,
+or you can use the *getFailure()* method to get the failure cause. 
Unfortunately both of these methods block until the promise
+resolves, and whilst the *isDone()* method does tell you if the Promise has 
completed they really aren't the right way to use a
+Promise.
+
+Promises work best when you register callbacks and/or transformations. The 
Promise API has a variety of useful methods for
+doing work with the Promise when it resolves. For example we can run a task 
after the promise completes successfully:
+
+       Promise<Integer> promise = ...
+       promise.then(p -> {
+                       System.out.println("The calculator returned " + 
p.getValue());
+                       return null;
+               });
+
+We can also register callbacks to handle failures:
+
+       Promise<Integer> promise = ...
+       promise.then(p -> {
+                       System.out.println("The calculator returned " + 
p.getValue());
+                       return null;
+               }, p -> p.getFailure().printStackTrace());
+
+### Chaining OSGi Promises
+
+In the previous examples our success callback returned *null* - why? Well the 
return value from a success callback is always
+a promise (null is a shortcut for a promise resolved with null). The promise 
returned by the callback represents an asynchronous 
+execution flow in a process known as "chaining". The overall completion of 
this chain is represented by a third promise, returned
+to the caller of the *then()* method.
+
+ 1. The caller registers a success callback, and receives a "chained" promise
+ 2. The original promise completes successfully
+ 3. The success callback runs and returns a promise representing another piece 
of asynchronous work
+ 4. The promise returned by the success callback completes successfully
+ 5. The "chained" promise completes with the same value as the promise from 
step 4.
+
+##Other Promise behaviours
+
+As well as simple callbacks Promises also provide advanced mapping and 
recovery features. For example a promise can be
+wrapped so that if the original work fails then a new value can be supplied 
using a recovery function.
+
+The *org.osgi.util.promise.Promises* utility class also provides useful 
functions for working with promises. For example helper
+methods to wrap an existing value or failure in a Promise, or a way of 
aggregating a group of promises into a single promise.
+
+
+#The Async service
+
+Most OSGi services have a synchronous API. This is usually the easiest way to 
think about, write, and use services. The main
+problem with this is that long running service calls can cause applications to 
run slowly, and making the calls asynchronous is
+both verbose and error-prone.
+
+The Async service is designed to take away the boilerplate code needed to 
invoke a service asynchronously, and to convert any
+synchronous API into an asynchronous API, returning promises instead of values.
+
+##Using the Async service
+
+The Async service is available in the service registry and is very easy to use 
- first we need to mediate the service. 
+Mediating is a bit like creating a mock object, the mediator records method 
calls made against it so that they can be 
+transformed into asynchronous calls. Mediating can apply to a concrete object, 
or to a ServiceReference. It is better to 
+use a ServiceReference when one is available, as the Async service can track 
the availability of the backing service.
+
+
+       Async async = ...;
+       ServiceReference<MyService> ref = ...;
+       MyService mediator = async.mediate(ref, MyService.class);
+
+*or*
+
+       Async async = ...;
+       MyService svc = ...;
+       MyService mediator = async.mediate(svc, MyService.class);
+
+Once a service has been mediated the mediator should be called just like the 
real service object, and the return value passed to
+the Async service's *call()* method. This returns a promise representing the 
asynchronous work.
+
+       Promise<Integer> promise =  
async.call(mediator.calculateReallyHardSum());
+
+### Void methods
+
+Void methods don't have a return value to pass to the async service, and 
should use the no-args version of call instead.
+
+       mediator.longRunningVoidMethod()
+       Promise<?> promise =  async.call();
+
+### Fire and Forget calls
+
+Sometimes the user does not care when a piece of work finishes, or what value 
it returns, or even whether it was successful.
+These sorts of calls are called "fire and forget" calls, and are also 
supported by the async service using the *execute()* method.
 
-##Introduction
-... tbd ...
+The execute method still returns a promise, however this promise represents 
whether the fire and forget call successfully started
+or not, not whether it has completed.
\ No newline at end of file

Propchange: aries/site/trunk/content/modules/async-svcs.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to