-
Notifications
You must be signed in to change notification settings - Fork 8
/
service.async.html
4773 lines (4696 loc) · 610 KB
/
service.async.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>138 Asynchronous Service Specification - OSGi Compendium 7</title>
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1" />
<link rel="home" href="toc.html" title="OSGi Compendium" />
<link rel="up" href="toc.html" title="OSGi Compendium" />
<link rel="prev" href="service.rest.html" title="137 REST Management Service Specification" />
<link rel="next" href="service.http.whiteboard.html" title="140 Http Whiteboard Specification" />
<meta name="Section-title" content="138 Asynchronous Service Specification" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="shortcut icon" href="images/favicon.png" type="image/x-icon" />
<link rel="stylesheet" type="text/css" href="css/custom.css" />
<link rel="stylesheet" type="text/css" href="css/github.css" />
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Ubuntu:regular,bold&subset=Latin" /><script type="text/javascript" src="js/highlight.pack.js"></script><script type="text/javascript" src="js/main.js"></script></head>
<body>
<div id="fullbody">
<div id="header">
<div class="menu-top-container"></div>
<div id="shadow-block"><a class="logo" href="index.html"><img src="images/logo.svg" alt="OSGi Alliance Documentation" /><h1>OSGi Compendium Release 7</h1></a></div>
</div>
<div id="mobile-menu-icon">⋮</div>
<div id="column-two">
<div id="content">
<div id="scrollable">
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<td width="20%" align="left"><a accesskey="p" href="service.rest.html">Prev</a>
</td>
<th width="60%" align="center"> </th>
<td width="20%" align="right"> <a accesskey="n" href="service.http.whiteboard.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="chapter">
<div xmlns="" class="titlepage">
<div>
<div>
<h1 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="service.async"></a><span xmlns="" class="number">138</span> Asynchronous Service Specification
</h1>
</div>
<div>
<p xmlns="http://www.w3.org/1999/xhtml" class="releaseinfo"><a xmlns="" class="xref" href="service.async.html#org.osgi.service.async" title="138.9 org.osgi.service.async">Version 1.0</a></p>
</div>
</div>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h2 xmlns="http://www.w3.org/1999/xhtml" class="title" style="clear: both"><a xmlns="" class="anchor" id="d0e118301"></a><span xmlns="" class="number">138.1</span> Introduction
</h2>
</div>
</div>
</div>
<p>OSGi Bundles collaborate using loosely coupled services registered
in the OSGi service registry. This is a powerful and flexible model, and
allows for the dynamic replacement of services at runtime. OSGi services
are therefore a very common interaction pattern within OSGi.
</p>
<p>As with most Java APIs and Objects, OSGi services are primarily
synchronous in operation. This has several benefits; synchronous APIs are
typically easier to write and to use than asynchronous ones; synchronous
APIs provide immediate feedback; synchronous implementations typically
have a less complex threading model.
</p>
<p>Asynchronous APIs, however, have different advantages. Asynchronous
APIs can reduce bottlenecks by encouraging more effective use of
parallelism, improving the responsiveness of the application. In many
cases high throughput systems can be written more simply and elegantly
using asynchronous programming techniques.
</p>
<p>The <a xmlns="" class="xref" href="util.promise.html" title="705 Promises Specification"><em xmlns="http://www.w3.org/1999/xhtml">Promises Specification</em></a> provides powerful primitives for
asynchronous programming, including the ability to compose flows in a
functional style. There are, however, many existing services that do not
use the Promise API. The purpose of the Asynchronous Service is to bridge
the gap between these existing, primarily synchronous, services in the
OSGi service registry, and asynchronous programming. The Asynchronous
Service therefore provides a way to invoke arbitrary OSGi services
asynchronously, providing results and failure notifications through the
Promise API.
</p>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118314"></a><span xmlns="" class="number">138.1.1</span> Essentials
</h3>
</div>
</div>
</div>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<p><span class="emphasis"><em>Async Invocation</em></span> - A single method call
that is to be executed without blocking the requesting
thread.
</p>
</li>
<li class="listitem">
<p><span class="emphasis"><em>Client</em></span> - Application code that wishes to
invoke one or more OSGi services asynchronously.
</p>
</li>
<li class="listitem">
<p><span class="emphasis"><em>Async Service</em></span> - The OSGi service
representing the Asynchronous Services implementation. Used by the
Client to make one or more Async Invocations.
</p>
</li>
<li class="listitem">
<p><span class="emphasis"><em>Async Mediator</em></span> - A mediator object
created by the Async Service which represents the target service.
Used by the Client to register Async Invocations.
</p>
</li>
<li class="listitem">
<p><span class="emphasis"><em>Success Callback</em></span> - A callback made when
an Async Invocation completes with a normal return value.
</p>
</li>
<li class="listitem">
<p><span class="emphasis"><em>Failure Callback</em></span> - A callback made when
an Async Invocation completes with an exception.
</p>
</li>
</ul>
</div>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118348"></a><span xmlns="" class="number">138.1.2</span> Entities
</h3>
</div>
</div>
</div>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<p><span class="emphasis"><em>Async Service</em></span> - A service that can create
Async Mediators and run Async Invocations.
</p>
</li>
<li class="listitem">
<p><span class="emphasis"><em>Target Service</em></span> - A service that is to be
called asynchronously by the Client.
</p>
</li>
<li class="listitem">
<p><span class="emphasis"><em>Client</em></span> - The code that makes Async
Invocations using the Async Service
</p>
</li>
<li class="listitem">
<p><span class="emphasis"><em>Promise</em></span> - A promise, representing the
result of the Async Invocation.
</p>
</li>
</ul>
</div>
<div class="figure"><a xmlns="" class="anchor" id="d0e118372"></a><p class="title"><strong>Figure <span xmlns="" class="number">138</span>.1 Class and Service overview</strong></p>
<div class="figure-contents">
<div class="mediaobject" align="center"><img src="images/138-async-classes.png" align="middle" width="630" height="189" alt="Class and Service overview" /></div>
</div>
</div><br class="figure-break" /></div>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h2 xmlns="http://www.w3.org/1999/xhtml" class="title" style="clear: both"><a xmlns="" class="anchor" id="d0e118378"></a><span xmlns="" class="number">138.2</span> Usage
</h2>
</div>
</div>
</div>
<p>This section is an introduction in the usage of the Async Service.
It is not the formal specification, the normative part starts at <a xmlns="" class="xref" href="service.async.html#service.async-main.body" title="138.3 Async Service">Async Service</a>. This section leaves out some of the
details for clarity.
</p>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118385"></a><span xmlns="" class="number">138.2.1</span> Synopsis
</h3>
</div>
</div>
</div>
<p>The Async Service provides a mechanism for a client to
<span class="emphasis"><em>asynchronously</em></span> invoke methods on a target service.
The service may be aware of the asynchronous nature of the call and
actively participate in it, or be unaware and execute normally. In
either case the client's thread will not block, and will continue
executing its next instructions. Clients are notified of the completion
of their task, and whether it was successful or not, through the use of
the Promise API.
</p>
<p>Each async invocation is registered by the client making a method
call on an <span class="emphasis"><em>Async Mediator</em></span>, and then started by
making a call to the Async Service that created the mediator. This call
returns a Promise that will eventually be resolved with the return value
from the async invocation.
</p>
<p>An Async Mediator can be created by the client, either from an
Object, or directly from a Service Reference. Using a service reference
has the advantage that the mediator will track the underlying service.
This means that if the service is unregistered before the asynchronous
call begins then the Promise will resolve with a failure, rather than
continuing using an invalid service object.
</p>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118400"></a><span xmlns="" class="number">138.2.2</span> Making Async Invocations
</h3>
</div>
</div>
</div>
<p>The general pattern for a client is to obtain the Async Service,
and a service reference for the target service. The client then creates
an Async Mediator for the target service, invokes a method on the
mediator, then starts the asynchronous call. This is demonstrated in the
following example:
</p><pre xmlns="" class="programlisting"><code>
private Async asyncService;
private ServiceReference<Foo> fooRef;
private Foo mediated;
@Reference
void setAsync(Async async) {
asyncService = async;
}
@Reference(service = Foo.class)
void setList(ServiceReference<Foo> foo) {
fooRef = foo;
}
@Activate
void start() {
mediated = asyncService.mediate(fooRef, Foo.class);
}
public synchronized void doStuff() {
Promise<Boolean> promise = asyncService
.call(mediated.booleanMethod(“aValue”));
...
}
</code></pre><p>This example demonstrates how simply clients can make asynchronous
calls using the Async Service. The eventual result can be obtained from
the promise using one of the relevant callbacks.
</p>
<p>One important thing to note is that whilst the call to <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call--" title="138.9.2.2 public Promise<?> call()">call()</a> or
<a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call-R-" title="138.9.2.1 public Promise<R> call(R r)">call(R)</a> causes the async invocation to begin, the actual
execution of the underlying task may be queued until a thread is
available to run it. If the service has been unregistered before the
execution actually begins then the promise will be resolved with a
Service Exception. The type of the Service Exception will be
<code class="code">ASYNC_ERROR</code>.
</p>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118418"></a><span xmlns="" class="number">138.2.3</span> Async Invocations of Void Methods
</h3>
</div>
</div>
</div>
<p>The return value of the mediator method call is used to provide
type information to the Async Service. This, however, does not work for
<code class="code">void</code> methods that have no return value. In this case the
client can either pass an arbitrary object to the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call-R-" title="138.9.2.1 public Promise<R> call(R r)">call(R)</a>
method, or use the zero argument <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call--" title="138.9.2.2 public Promise<?> call()">call()</a>
method. In either case the returned promise will eventually resolve with
a value of <code class="code">null</code>. This is demonstrated in the following
example.
</p><pre xmlns="" class="programlisting"><code>
private Async asyncService;
private ServiceReference<Foo> fooRef;
private Foo mediated;
@Reference
void setAsync(Async async) {
asyncService = async;
}
@Reference(service = Foo.class)
void setList(ServiceReference<Foo> foo) {
fooRef = foo;
}
@Activate
void start() {
mediated = asyncService.mediate(fooRef, Foo.class);
}
public synchronized void doStuff() {
mediated.voidMethod();
Promise<?> promise = asyncService
.call();
...
}</code></pre></div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118435"></a><span xmlns="" class="number">138.2.4</span> Fire and Forget Calls
</h3>
</div>
</div>
</div>
<p>Sometimes a client does not require any notification that an async
invocation has completed. In this case the client could use one of the
<a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call--" title="138.9.2.2 public Promise<?> call()">call()</a> or <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call-R-" title="138.9.2.1 public Promise<R> call(R r)">call(R)</a>
methods and simply discard the returned Promise object. This, however,
can be wasteful of resources. The act of resolving the Promise object
may be expensive, for example it may involve serializing the return
value over a network if the remote call was asynchronous.
</p>
<p>If the client knows that no Promise object representing the result
of the asynchronous task is needed then it can signal this to the Async
Service. This allows the Async Service to better optimize the async
invocation by not providing a result.
</p>
<p>To indicate that the client wants to make a fire-and-forget style
call the client invokes the mediator as normal, but then begins the
asynchronous invocation using the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.execute--" title="138.9.2.3 public Promise<Void> execute()">execute()</a>
method as show below.
</p><pre xmlns="" class="programlisting"><code>
private Async asyncService;
private ServiceReference<Foo> fooRef;
private Foo mediated;
@Reference
void setAsync(Async async) {
asyncService = async;
}
@Reference(service = Foo.class)
void setList(ServiceReference<Foo> foo) {
fooRef = foo;
}
@Activate
void start() {
mediated = asyncService.mediate(fooRef, Foo.class);
}
public synchronized void doStuff() {
mediated.someMethod();
asyncService.execute();
...
}</code></pre><p>Note that the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.execute--" title="138.9.2.3 public Promise<Void> execute()">execute()</a>
method does still return a Promise. This Promise is not the same as the
ones returned by <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call--" title="138.9.2.2 public Promise<?> call()">call()</a> or <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call-R-" title="138.9.2.1 public Promise<R> call(R r)">call(R)</a>,
its resolution value does not provide access to the result, but instead
indicates whether the fire-and-forget call could be successfully
started. If there is a failure which prevents the task from being
executed then this is used to fail the returned promise.
</p>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118460"></a><span xmlns="" class="number">138.2.5</span> Multi Threading
</h3>
</div>
</div>
</div>
<p>By their very definition asynchronous tasks do not run inline, and
typically they will not run on the same thread as the caller. This is
not, however, a guarantee. A valid implementation of the Async Service
may have only one worker thread, which may be the thread currently
running in the client code. Async invocations also have the same
threading model as the Promise API. This means that callbacks may run on
arbitrary threads, which may, or may not, be the same as the client
thread, or the thread which executed the asynchronous work.
</p>
<p>It is important for multi-threaded clients to note that calls to
the mediator and Async Service must occur on the same thread. For
example it is not supported to invoke a mediator using one thread, and
then to begin the async invocation by calling the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call--" title="138.9.2.2 public Promise<?> call()">call()</a>,
<a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call-R-" title="138.9.2.1 public Promise<R> call(R r)">call(R)</a> or <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.execute--" title="138.9.2.3 public Promise<Void> execute()">execute()</a>
method on a different thread.
</p>
</div>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h2 xmlns="http://www.w3.org/1999/xhtml" class="title" style="clear: both"><a xmlns="" class="anchor" id="service.async-main.body"></a><span xmlns="" class="number">138.3</span> Async Service
</h2>
</div>
</div>
</div>
<p>The Async Service is the primary interaction point between a client
and the Async Service implementation. An Async Service implementation must
expose a service implementing the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async" title="138.9.2 public interface Async">Async</a> interface.
Clients obtain an instance of the Async Service using the normal OSGi
service registry mechanisms, either directly using the OSGi framework API,
or using dependency injection.
</p>
<p>The Async Service is used to:</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<p>Create async mediators</p>
</li>
<li class="listitem">
<p>Begin async invocations</p>
</li>
<li class="listitem">
<p>Obtain Promise objects representing the result of the async
invocation
</p>
</li>
</ul>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118492"></a><span xmlns="" class="number">138.3.1</span> Using the Async Service
</h3>
</div>
</div>
</div>
<p>The first action that a client wishing to make an async invocation
must take is to create an async mediator using one of the
<code class="code">mediate</code> methods. Once created the client invokes the method
that should be run asynchronously, supplying the arguments that should
be used. This call records the invocation, but does not start the
asynchronous task. The asynchronous task begins when the client invokes
one of the <code class="code">call</code> or <code class="code">execute</code> methods on the
Async Service. The <code class="code">call</code> methods must return a Promise
representing the async invocation. The promise must resolve with the
value returned by the async invocation, or fail with the failure thrown
by the async invocation.
</p>
<p>If the client attempts to begin an async invocation without first
having called a method on the mediator object then the Async Service
must detect this usage error and throw an
<code class="code">IllegalStateException</code> to the client. This applies to all
methods that begin an async invocation.
</p>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="service.async-main.failures"></a><span xmlns="" class="number">138.3.2</span> Asynchronous Failures
</h3>
</div>
</div>
</div>
<p>There are a variety of reasons that async invocations may be
started correctly by the client, but then fail without running the
asynchronous task. In any of these cases the Promise representing the
async invocation must fail with a Service Exception. This Service
Exception must be initialized with a type of <code class="code">ASYNC_ERROR</code>.
If there is no promise representing the async invocation then there is
no way to notify the client of the failure, therefore the Service
Exception must be logged by the Async Service using all available Log
Service implementations.
</p>
<p>The following list of scenarios is not exhaustive, but indicates
failure scenarios that must result in a Service Exception with a type of
async
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<p>If the client is using a service reference backed mediator and
the client bundle's bundle context becomes invalid before looking up
the target service.
</p>
</li>
<li class="listitem">
<p>If the client is using a service reference backed mediator and
the service is unregistered before making the async
invocation.
</p>
</li>
<li class="listitem">
<p>If the client is using a service reference backed mediator and
the service lookup returns <code class="code">null</code></p>
</li>
<li class="listitem">
<p>If the Async Service is unable to accept new work, for example
it is in the process of being shut down.
</p>
</li>
<li class="listitem">
<p>If the type of the mediator object does not match the type of
the service object to be invoked.
</p>
</li>
</ul>
</div>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118542"></a><span xmlns="" class="number">138.3.3</span> Thread Safety and Instance Sharing
</h3>
</div>
</div>
</div>
<p>Implementations of the Async Service must be thread safe and may
be used simultaneously across multiple clients and from multiple threads
within the same client. Whilst the Async Service is able to be used
across multiple threads, if a client wishes to make an async invocation
then the call to the mediator and the call to begin the async invocation
must occur on the same thread. The returned Promise may then be shared
between threads if required.
</p>
<p>It is expected, although not required, that the Async Service
implementation will use a Service Factory to create customized
implementations for each client bundle. This simplifies the tracking of
the relevant client bundle context to use when performing service
lookups on the client bundle's behalf. Clients should therefore not
share instances of the Async Service with other bundles. Instead both
bundles should obtain their own instances from the service
registry.
</p>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118549"></a><span xmlns="" class="number">138.3.4</span> Service Object Lifecycle Management
</h3>
</div>
</div>
</div>
<p>If the Async Service is being used to call an OSGi service object
and the service reference is available then the service object should be
looked up immediately before the asynchronous task begins executing.
This ensures that the service is still available at the point it is
eventually called. Any call to <code class="code">getService</code> must have a
corresponding call to <code class="code">ungetService</code> after the mediated
method invoked has returned and, if available, the promise is resolved,
but before the asynchronous task releases its thread of
execution.
</p>
</div>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h2 xmlns="http://www.w3.org/1999/xhtml" class="title" style="clear: both"><a xmlns="" class="anchor" id="d0e118560"></a><span xmlns="" class="number">138.4</span> The Async Mediator
</h2>
</div>
</div>
</div>
<p>Async mediators are dynamically created objects that have the same
type or interface as the object being mediated, and are used to record
method invocations and arguments. Mediator objects are specific to an
Async Service implementation, and must only be used in conjunction with
the Async Service object that they were created by.
</p>
<p>Mediators may be created either from a <code class="code">ServiceReference</code>
or from a service object. The actions and overall result are similar for
both the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.mediate-ServiceReference-Class-" title="138.9.2.5 public T mediate(ServiceReference<? extends T> target, Class<T> iface)">mediate(ServiceReference,Class)</a> and <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.mediate-T-Class-" title="138.9.2.4 public T mediate(T target, Class<T> iface)">mediate(T,Class)</a> methods, with the primary difference being that
mediated objects created from a <code class="code">ServiceReference</code> will
validate whether the service object is still available immediately before
the asynchronous task is executed.
</p>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118577"></a><span xmlns="" class="number">138.4.1</span> Building the Mediator Object
</h3>
</div>
</div>
</div>
<p>The client passes in a <code class="code">Class</code> indicating the type that
should be mediated. If the class object represents an interface type
then the generated mediator object must implement that interface. If the
class object represents a Java class type then the mediator object must
either be an instance of that type or extend it.
</p>
<p>When building a mediator object the Async Service has the
opportunity to detect numerous problems, for example if the referenced
service to be mediated has been unregistered. Although fail-fast
behavior is usually preferable, in this case it would force the client
to handle errors in two places; both when creating the mediator, and for
the returned Promise. To simplify client usage, error cases detected
when creating a mediator must not prevent the mediator from being
created and must not result in an exception being thrown. The only
reason that the Async Service may fail to create a mediator is if the
class object passed in cannot be mediated.
</p>
<p>There are three reasons why the Async Service may not be able to
mediate a class type:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<p>The class object passed in represents a final type.</p>
</li>
<li class="listitem">
<p>The class object passed in represents a type that has no
zero-argument constructor.
</p>
</li>
<li class="listitem">
<p>The class object passed in represents a type which has one or
more public final methods present in its type hierarchy (other than
those declared by <code class="code">java.lang.Object</code>).
</p>
</li>
</ul>
</div>
<p>If any of these constraints are violated and prevent the Async
Service from creating a mediator then the Async Service must throw an
IllegalArgumentException.
</p>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118604"></a><span xmlns="" class="number">138.4.2</span> Async Mediator Behaviors
</h3>
</div>
</div>
</div>
<p>When invoked, the Async mediator must record the method call, and
its arguments, and then return rapidly and should avoid performing
blocking operations. The values returned by the mediator object are
opaque, and the client should not attempt to interpret the returned
value. The value may be null (or null-like in the case of primitives) or
contain implementation specific information. If the mediated method call
has a return type, specifically it is non-void, then this object must be
passed to the Async Service's <code class="code">call</code> method when beginning
the async invocation
</p>
<p>Async mediators should make a best-effort attempt to detect
incorrect API usage from the client. If this incorrect usage is detected
then the mediator object must throw an IllegalStateException when
invoked. An example of incorrect usage that must be detected is when a
client makes multiple invocations on a single mediator object from the
same thread without making any calls to the Async Service.
</p>
<p>After a usage error has been detected and an IllegalStateException
has been thrown the mediator object must be reset so that a subsequent
invocation from the client thread can proceed normally.
</p>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118616"></a><span xmlns="" class="number">138.4.3</span> Thread Safety and Instance Sharing
</h3>
</div>
</div>
</div>
<p>Async mediators, like instances of the Async Service, are required
to be thread safe. Clients may therefore share mediator objects across
threads, and can safely store them as instance fields. Whilst mediators
are thread safe, if a client wishes to make an async invocation then the
call to the mediator and the call to <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call--" title="138.9.2.2 public Promise<?> call()">call()</a> or
<a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call-R-" title="138.9.2.1 public Promise<R> call(R r)">call(R)</a> must occur on the same thread. The returned
Promise may then be shared between threads if required.
</p>
<p>Async mediators created from <code class="code">ServiceReference</code> objects
remain directly associated with the service reference and client bundle
after creation. Clients should therefore not share mediator objects with
other bundles. Instead each bundle should create its own
mediator.
</p>
</div>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h2 xmlns="http://www.w3.org/1999/xhtml" class="title" style="clear: both"><a xmlns="" class="anchor" id="d0e118630"></a><span xmlns="" class="number">138.5</span> Fire and Forget Invocations
</h2>
</div>
</div>
</div>
<p>The Async Service provides <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call--" title="138.9.2.2 public Promise<?> call()">call()</a> and
<a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call-R-" title="138.9.2.1 public Promise<R> call(R r)">call(R)</a> methods for clients to use when they wish to
receive results from asynchronous tasks. Clients that do not need the
result can simply discard the returned Promise object. This, however, can
be wasteful of resources. The act of resolving the Promise object may be
expensive, for example it may involve serializing the return value over a
network.
</p>
<p>To address this use case the Async Service provides the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.execute--" title="138.9.2.3 public Promise<Void> execute()">execute()</a>
method, which behaves similarly to <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call--" title="138.9.2.2 public Promise<?> call()">call()</a> and
<a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call-R-" title="138.9.2.1 public Promise<R> call(R r)">call(R)</a>, but does not provide access to the eventual
result. Instead the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.execute--" title="138.9.2.3 public Promise<Void> execute()">execute()</a> method returns a <code class="code">Promise</code> that
indicates whether the fire-and-forget call is able to be successfully
started.
</p>
<p>The returned Promise must be resolved with <code class="code">null</code> if the
asynchronous task begins executing successfully. There is no
<span class="emphasis"><em>happens-before</em></span> relationship required, meaning that if
the Promise resolves successfully then the task may, or may not, have
started or finished. The primary usage of the Promise is actually to
detect failures. If the fire-and-forget task cannot be executed for some
reason, for example the backing service has been unregistered, then the
returned promise must be failed appropriately using the same rules as
defined in <a xmlns="" class="xref" href="service.async.html#service.async-main.failures" title="138.3.2 Asynchronous Failures">Asynchronous Failures</a>. If the returned
Promise is failed then the fire-and-forget task has not executed and will
not execute in the future.
</p>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h2 xmlns="http://www.w3.org/1999/xhtml" class="title" style="clear: both"><a xmlns="" class="anchor" id="d0e118662"></a><span xmlns="" class="number">138.6</span> Delegating to Asynchronous Implementations
</h2>
</div>
</div>
</div>
<p>Some service APIs are already asynchronous in operation, and others
are partly asynchronous, in that some methods run asynchronously and
others do not. There are also services which have a synchronous API, but
could run asynchronously because they are a proxy to another service. A
good example of this kind of service is a remote service. Remote services
are local views of a remote endpoint, and depending upon the
implementation of the endpoint it may be possible to make the remote call
asynchronously, optimizing the thread usage of any local asynchronous
call.
</p>
<p>Services that already have some level of asynchronous support may
advertise this to clients and to the Async Service by having their service
object be an <code class="code">instanceof</code> <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.delegate.AsyncDelegate" title="138.10.2 public interface AsyncDelegate">AsyncDelegate</a>. The service object can be cast to <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.delegate.AsyncDelegate" title="138.10.2 public interface AsyncDelegate">AsyncDelegate</a> to be used by the Async Service implementation, or
by the client directly, to make an asynchronous call on the
service.
</p>
<p>Because the Async Delegate behavior is transparently handled by the
Async Service, clients of the Async Service do not need to know whether
the service object is an <code class="code">instanceof</code> <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.delegate.AsyncDelegate" title="138.10.2 public interface AsyncDelegate">AsyncDelegate</a> or not. Their usage pattern can remain
unchanged.
</p>
<p>When making an async invocation, the Async Service must check to see
whether the service object is an <code class="code">instanceof</code> <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.delegate.AsyncDelegate" title="138.10.2 public interface AsyncDelegate">AsyncDelegate</a>. If the service object is an
<code class="code">instanceof</code> <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.delegate.AsyncDelegate" title="138.10.2 public interface AsyncDelegate">AsyncDelegate</a>, then the Async Service must attempt to delegate
the asynchronous call. The exact delegation operation depends on whether a
Promise result is required.
</p>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118695"></a><span xmlns="" class="number">138.6.1</span> Obtaining a Promise from an Async Delegate
</h3>
</div>
</div>
</div>
<p>If the result of the method invocation is needed by the client,
then the Async Service must attempt to delegate to the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.delegate.AsyncDelegate.async-Method-Object---" title="138.10.2.1 public Promise<?> async(Method m, Object[] args) throws Exception">async(Method,Object[])</a> method. The delegation proceeds as
follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<p>If the call to the Async Delegate returns a Promise, then the
Promise returned by the Async Service must be resolved with that
Promise.
</p>
</li>
<li class="listitem">
<p>If the call to the Async Delegate throws an exception, then
the Promise returned by the Async Service must be failed with the
exception.
</p>
</li>
<li class="listitem">
<p>If the Async Delegate is unable to optimize the call and
returns <code class="code">null</code> from the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.delegate.AsyncDelegate.async-Method-Object---" title="138.10.2.1 public Promise<?> async(Method m, Object[] args) throws Exception">async(Method,Object[])</a> method, the Async Service must continue
processing the async invocation, treating the service as a normal
service object.
</p>
</li>
</ul>
</div>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118717"></a><span xmlns="" class="number">138.6.2</span> Delegating Fire and Forget Calls to an Async Delegate
</h3>
</div>
</div>
</div>
<p>If the result of the method invocation is not needed by the
client, then the Async Service must attempt to delegate to the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.delegate.AsyncDelegate.execute-Method-Object---" title="138.10.2.2 public boolean execute(Method m, Object[] args) throws Exception">execute(Method,Object[])</a> method. This gives the Async Delegate
implementation the opportunity to further optimize its processing. The
delegation proceeds as follows:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<p>If the call to the Async Delegate returns <code class="code">true</code>,
then the Promise returned by the Async Service must be resolved with
<code class="code">null</code>.
</p>
</li>
<li class="listitem">
<p>If the call to the Async Delegate throws an exception, then
the Promise returned by the Async Service must be failed with the
exception.
</p>
</li>
<li class="listitem">
<p>If the Async Delegate is unable to optimize the call and
returns <code class="code">false</code> from the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.delegate.AsyncDelegate.execute-Method-Object---" title="138.10.2.2 public boolean execute(Method m, Object[] args) throws Exception">execute(Method,Object[])</a> method, the Async Service must continue
processing the async invocation, treating the service as a normal
service object.
</p>
</li>
</ul>
</div>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a xmlns="" class="anchor" id="d0e118745"></a><span xmlns="" class="number">138.6.3</span> Lifecycle for Service Objects When Delegating
</h3>
</div>
</div>
</div>
<p>If an Async Delegate implementation accepts an asynchronous task,
via a call to either <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.delegate.AsyncDelegate.execute-Method-Object---" title="138.10.2.2 public boolean execute(Method m, Object[] args) throws Exception">execute(Method,Object[])</a> or <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.delegate.AsyncDelegate.async-Method-Object---" title="138.10.2.1 public Promise<?> async(Method m, Object[] args) throws Exception">async(Method,Object[])</a>, then it is responsible for continuing to
process the work until completion. This means that if the service
implementing Async Delegate is unregistered for some reason, then the
task must be properly cleaned up and succeed or fail as
appropriate.
</p>
<p>If the Async Service implementation used a service reference to
obtain the service, then it must release the service object after the
task has been accepted. This means that if the service object is
provided by a service factory, then the service object should take extra
care not to destroy its internal state when released. The service object
must remain valid until all executing asynchronous tasks associated with
the service object are either completed or failed.
</p>
<p>If an Async Delegate implementation rejects an asynchronous task,
by returning <code class="code">false</code> or <code class="code">null</code>, the Async Service
implementation must take over the asynchronous invocation of the method.
In this case, if the Async Service implementation used a service
reference to obtain the service, the Async Service must not release the
service object until the asynchronous task is completed.
</p>
<p>If an Async Delegate implementation throws an exception and the
Async Service implementation used a service reference to obtain the
service, then the service object must be released immediately.
</p>
</div>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h2 xmlns="http://www.w3.org/1999/xhtml" class="title" style="clear: both"><a xmlns="" class="anchor" id="service.async-capabilities"></a><span xmlns="" class="number">138.7</span> Capabilities
</h2>
</div>
</div>
</div>
<p>Implementations of the Asynchronous Service specification must
provide the following capabilities.
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<p>A capability in the <a xmlns="" class="link" href="service.namespaces.html#service.namespaces-osgi.implementation.namespace" title="135.5 osgi.implementation Namespace"><code xmlns="http://www.w3.org/1999/xhtml" class="code">osgi.implementation</code></a>
namespace declaring the implemented specification to be
<code class="code">osgi.async</code>. This capability must also declare a uses
constraint for the <code class="code">org.osgi.service.async</code> and
<code class="code">org.osgi.service.async.delegate</code> packages. For
example:
</p><pre xmlns="" class="programlisting"><code>Provide-Capability: osgi.implementation;
osgi.implementation="osgi.async";
version:Version="<a class="xref" href="service.async.html#org.osgi.service.async" title="138.9 org.osgi.service.async">1.0</a>";
uses:="org.osgi.service.async,org.osgi.service.async.delegate"</code></pre><p>This capability must follow the rules defined for the <a xmlns="" class="xref" href="service.namespaces.html#service.namespaces-osgi.implementation.namespace" title="135.5 osgi.implementation Namespace">osgi.implementation Namespace</a>.
</p>
</li>
<li class="listitem">
<p>A capability in the <a xmlns="" class="link" href="service.namespaces.html#service.namespaces-osgi.service.namespace" title="135.4 osgi.service Namespace"><code xmlns="http://www.w3.org/1999/xhtml" class="code">osgi.service</code></a>
namespace representing the <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async" title="138.9.2 public interface Async">Async</a>
service. This capability must also declare a uses constraint for the
<code class="code">org.osgi.service.async</code> package. For example:
</p><pre xmlns="" class="programlisting"><code>Provide-Capability: osgi.service;
objectClass:List<String>="org.osgi.service.async.Async";
uses:="org.osgi.service.async"</code></pre><p>This capability must follow the rules defined for the <a xmlns="" class="xref" href="service.namespaces.html#service.namespaces-osgi.service.namespace" title="135.4 osgi.service Namespace">osgi.service Namespace</a>.
</p>
</li>
</ul>
</div>
</div>
<div class="section">
<div xmlns="" class="titlepage">
<div>
<div>
<h2 xmlns="http://www.w3.org/1999/xhtml" class="title" style="clear: both"><a xmlns="" class="anchor" id="service.async-security"></a><span xmlns="" class="number">138.8</span> Security
</h2>
</div>
</div>
</div>
<p>Asynchronous Services implementations must be careful to avoid
elevating the privileges of client bundles when calling services
asynchronously, and also to avoid restricting the privileges of clients
that are permitted to make a call. This means that the implementation
must:
</p>
<div class="itemizedlist">
<ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<p>Be granted <code class="code">AllPermission</code>. As the Async Service will
always be on the stack when invoking a service object asynchronously
it must be granted <code class="code">AllPermission</code> so that it does not
interfere with security any checks made by the service object.
</p>
</li>
<li class="listitem">
<p>Establish the caller's <code class="code">AccessControlContext</code> in a
worker thread before starting to call the service object. This
prevents a bundle from being able to call a service asynchronously
that it would not normally be able to call. The
<code class="code">AccessControlContext</code> must be collected during any call to
<a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call--" title="138.9.2.2 public Promise<?> call()">call()</a>, <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call-R-" title="138.9.2.1 public Promise<R> call(R r)">call(R)</a>
or <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.execute--" title="138.9.2.3 public Promise<Void> execute()">execute()</a>.
</p>
</li>
<li class="listitem">
<p>Use a <code class="code">doPrivileged</code> block when mediating a concrete
type. A no-args constructor in a concrete type may perform actions
that the client may not have permission to perform. This should not
prevent the client from mediating the object, as the client is not
directly performing these actions.
</p>
</li>
<li class="listitem">
<p>If the mediator object was created using a service reference,
then the Async Services implementation must use the client's bundle
context when retrieving the target service. If the service lookup
occurs on a worker thread, then the lookup must use the
<code class="code">AccessControlContext</code> collected during the call to <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call--" title="138.9.2.2 public Promise<?> call()">call()</a>,
<a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.call-R-" title="138.9.2.1 public Promise<R> call(R r)">call(R)</a> or <a xmlns="" class="xref" href="service.async.html#org.osgi.service.async.Async.execute--" title="138.9.2.3 public Promise<Void> execute()">execute()</a>. This prevents the client bundle from being
able to make calls on a service object that they do not have
permission to obtain, and ensures that an appropriately customized
object is returned if the service is implemented using a service
factory.
</p>
</li>
</ul>
</div>
<p>Further security considerations can be addressed using normal OSGi
security rules. For example access to the Async Service can be controlled
using <code class="code">ServicePermission[...Async, GET]</code>.
</p>
</div>
<div class="section package">
<div xmlns="" class="titlepage">
<div>
<div>
<h2 xmlns="http://www.w3.org/1999/xhtml" class="title" style="clear: both"><a xmlns="" class="anchor" id="org.osgi.service.async"></a><span xmlns="" class="number">138.9</span> org.osgi.service.async
</h2>
</div>
<div>
<p xmlns="http://www.w3.org/1999/xhtml" class="releaseinfo">Version 1.0</p>
</div>
</div>
</div>
<p>
Asynchronous Services Package Version 1.0.
</p>
<p>