PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/akka-docs/rst/java/code/docs/future/FutureDocTest.java

https://github.com/migue/akka
Java | 592 lines | 419 code | 82 blank | 91 comment | 23 complexity | 806dc6a4c2a7191a59f84858d2518f10 MD5 | raw file
  1. /**
  2. * Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
  3. */
  4. package docs.future;
  5. //#imports1
  6. import akka.dispatch.*;
  7. import scala.concurrent.ExecutionContext;
  8. import scala.concurrent.Future;
  9. import scala.concurrent.Await;
  10. import scala.concurrent.Promise;
  11. import akka.util.Timeout;
  12. //#imports1
  13. //#imports2
  14. import scala.concurrent.duration.Duration;
  15. import akka.japi.Function;
  16. import java.util.concurrent.Callable;
  17. import static akka.dispatch.Futures.future;
  18. import static java.util.concurrent.TimeUnit.SECONDS;
  19. //#imports2
  20. //#imports3
  21. import static akka.dispatch.Futures.sequence;
  22. //#imports3
  23. //#imports4
  24. import static akka.dispatch.Futures.traverse;
  25. //#imports4
  26. //#imports5
  27. import akka.japi.Function2;
  28. import static akka.dispatch.Futures.fold;
  29. //#imports5
  30. //#imports6
  31. import static akka.dispatch.Futures.reduce;
  32. //#imports6
  33. //#imports7
  34. import scala.concurrent.ExecutionContext;
  35. import scala.concurrent.ExecutionContext$;
  36. //#imports7
  37. //#imports8
  38. import static akka.pattern.Patterns.after;
  39. import java.util.Arrays;
  40. //#imports8
  41. import java.util.ArrayList;
  42. import java.util.List;
  43. import java.util.concurrent.ExecutorService;
  44. import java.util.concurrent.Executors;
  45. import akka.testkit.AkkaJUnitActorSystemResource;
  46. import org.junit.ClassRule;
  47. import org.junit.Test;
  48. import akka.testkit.AkkaSpec;
  49. import akka.actor.Status.Failure;
  50. import akka.actor.ActorSystem;
  51. import akka.actor.UntypedActor;
  52. import akka.actor.ActorRef;
  53. import akka.actor.Props;
  54. import akka.pattern.Patterns;
  55. import static org.junit.Assert.*;
  56. public class FutureDocTest {
  57. @ClassRule
  58. public static AkkaJUnitActorSystemResource actorSystemResource =
  59. new AkkaJUnitActorSystemResource("FutureDocTest", AkkaSpec.testConf());
  60. private final ActorSystem system = actorSystemResource.getSystem();
  61. public final static class PrintResult<T> extends OnSuccess<T> {
  62. @Override public final void onSuccess(T t) {
  63. // print t
  64. }
  65. }
  66. public final static class Demo {
  67. //#print-result
  68. public final static class PrintResult<T> extends OnSuccess<T> {
  69. @Override public final void onSuccess(T t) {
  70. System.out.println(t);
  71. }
  72. }
  73. //#print-result
  74. }
  75. @SuppressWarnings("unchecked") @Test public void useCustomExecutionContext() throws Exception {
  76. ExecutorService yourExecutorServiceGoesHere = Executors.newSingleThreadExecutor();
  77. //#diy-execution-context
  78. ExecutionContext ec =
  79. ExecutionContexts.fromExecutorService(yourExecutorServiceGoesHere);
  80. //Use ec with your Futures
  81. Future<String> f1 = Futures.successful("foo");
  82. // Then you shut down the ExecutorService at the end of your application.
  83. yourExecutorServiceGoesHere.shutdown();
  84. //#diy-execution-context
  85. }
  86. @Test
  87. public void useBlockingFromActor() throws Exception {
  88. ActorRef actor = system.actorOf(Props.create(MyActor.class));
  89. String msg = "hello";
  90. //#ask-blocking
  91. Timeout timeout = new Timeout(Duration.create(5, "seconds"));
  92. Future<Object> future = Patterns.ask(actor, msg, timeout);
  93. String result = (String) Await.result(future, timeout.duration());
  94. //#ask-blocking
  95. //#pipe-to
  96. akka.pattern.Patterns.pipe(future, system.dispatcher()).to(actor);
  97. //#pipe-to
  98. assertEquals("HELLO", result);
  99. }
  100. @Test
  101. public void useFutureEval() throws Exception {
  102. //#future-eval
  103. Future<String> f = future(new Callable<String>() {
  104. public String call() {
  105. return "Hello" + "World";
  106. }
  107. }, system.dispatcher());
  108. f.onSuccess(new PrintResult<String>(), system.dispatcher());
  109. //#future-eval
  110. String result = (String) Await.result(f, Duration.create(5, SECONDS));
  111. assertEquals("HelloWorld", result);
  112. }
  113. @Test
  114. public void useMap() throws Exception {
  115. //#map
  116. final ExecutionContext ec = system.dispatcher();
  117. Future<String> f1 = future(new Callable<String>() {
  118. public String call() {
  119. return "Hello" + "World";
  120. }
  121. }, ec);
  122. Future<Integer> f2 = f1.map(new Mapper<String, Integer>() {
  123. public Integer apply(String s) {
  124. return s.length();
  125. }
  126. }, ec);
  127. f2.onSuccess(new PrintResult<Integer>(), system.dispatcher());
  128. //#map
  129. int result = Await.result(f2, Duration.create(5, SECONDS));
  130. assertEquals(10, result);
  131. }
  132. @Test
  133. public void useMap2() throws Exception {
  134. //#map2
  135. final ExecutionContext ec = system.dispatcher();
  136. Future<String> f1 = future(new Callable<String>() {
  137. public String call() throws Exception {
  138. Thread.sleep(100);
  139. return "Hello" + "World";
  140. }
  141. }, ec);
  142. Future<Integer> f2 = f1.map(new Mapper<String, Integer>() {
  143. public Integer apply(String s) {
  144. return s.length();
  145. }
  146. }, ec);
  147. f2.onSuccess(new PrintResult<Integer>(), system.dispatcher());
  148. //#map2
  149. int result = Await.result(f2, Duration.create(5, SECONDS));
  150. assertEquals(10, result);
  151. }
  152. @Test
  153. public void useMap3() throws Exception {
  154. //#map3
  155. final ExecutionContext ec = system.dispatcher();
  156. Future<String> f1 = future(new Callable<String>() {
  157. public String call() {
  158. return "Hello" + "World";
  159. }
  160. }, ec);
  161. // Thread.sleep is only here to prove a point
  162. Thread.sleep(100); // Do not use this in your code
  163. Future<Integer> f2 = f1.map(new Mapper<String, Integer>() {
  164. public Integer apply(String s) {
  165. return s.length();
  166. }
  167. }, ec);
  168. f2.onSuccess(new PrintResult<Integer>(), system.dispatcher());
  169. //#map3
  170. int result = Await.result(f2, Duration.create(5, SECONDS));
  171. assertEquals(10, result);
  172. }
  173. @Test
  174. public void useFlatMap() throws Exception {
  175. //#flat-map
  176. final ExecutionContext ec = system.dispatcher();
  177. Future<String> f1 = future(new Callable<String>() {
  178. public String call() {
  179. return "Hello" + "World";
  180. }
  181. }, ec);
  182. Future<Integer> f2 = f1.flatMap(new Mapper<String, Future<Integer>>() {
  183. public Future<Integer> apply(final String s) {
  184. return future(new Callable<Integer>() {
  185. public Integer call() {
  186. return s.length();
  187. }
  188. }, ec);
  189. }
  190. }, ec);
  191. f2.onSuccess(new PrintResult<Integer>(), system.dispatcher());
  192. //#flat-map
  193. int result = Await.result(f2, Duration.create(5, SECONDS));
  194. assertEquals(10, result);
  195. }
  196. @Test
  197. public void useSequence() throws Exception {
  198. List<Future<Integer>> source = new ArrayList<Future<Integer>>();
  199. source.add(Futures.successful(1));
  200. source.add(Futures.successful(2));
  201. //#sequence
  202. final ExecutionContext ec = system.dispatcher();
  203. //Some source generating a sequence of Future<Integer>:s
  204. Iterable<Future<Integer>> listOfFutureInts = source;
  205. // now we have a Future[Iterable[Integer]]
  206. Future<Iterable<Integer>> futureListOfInts = sequence(listOfFutureInts, ec);
  207. // Find the sum of the odd numbers
  208. Future<Long> futureSum = futureListOfInts.map(
  209. new Mapper<Iterable<Integer>, Long>() {
  210. public Long apply(Iterable<Integer> ints) {
  211. long sum = 0;
  212. for (Integer i : ints)
  213. sum += i;
  214. return sum;
  215. }
  216. }, ec);
  217. futureSum.onSuccess(new PrintResult<Long>(), system.dispatcher());
  218. //#sequence
  219. long result = Await.result(futureSum, Duration.create(5, SECONDS));
  220. assertEquals(3L, result);
  221. }
  222. @Test
  223. public void useTraverse() throws Exception {
  224. //#traverse
  225. final ExecutionContext ec = system.dispatcher();
  226. //Just a sequence of Strings
  227. Iterable<String> listStrings = Arrays.asList("a", "b", "c");
  228. Future<Iterable<String>> futureResult = traverse(listStrings,
  229. new Function<String, Future<String>>() {
  230. public Future<String> apply(final String r) {
  231. return future(new Callable<String>() {
  232. public String call() {
  233. return r.toUpperCase();
  234. }
  235. }, ec);
  236. }
  237. }, ec);
  238. //Returns the sequence of strings as upper case
  239. futureResult.onSuccess(new PrintResult<Iterable<String>>(), system.dispatcher());
  240. //#traverse
  241. Iterable<String> result = Await.result(futureResult, Duration.create(5, SECONDS));
  242. assertEquals(Arrays.asList("A", "B", "C"), result);
  243. }
  244. @Test
  245. public void useFold() throws Exception {
  246. List<Future<String>> source = new ArrayList<Future<String>>();
  247. source.add(Futures.successful("a"));
  248. source.add(Futures.successful("b"));
  249. //#fold
  250. final ExecutionContext ec = system.dispatcher();
  251. //A sequence of Futures, in this case Strings
  252. Iterable<Future<String>> futures = source;
  253. //Start value is the empty string
  254. Future<String> resultFuture = fold("", futures,
  255. new Function2<String, String, String>() {
  256. public String apply(String r, String t) {
  257. return r + t; //Just concatenate
  258. }
  259. }, ec);
  260. resultFuture.onSuccess(new PrintResult<String>(), system.dispatcher());
  261. //#fold
  262. String result = Await.result(resultFuture, Duration.create(5, SECONDS));
  263. assertEquals("ab", result);
  264. }
  265. @Test
  266. public void useReduce() throws Exception {
  267. List<Future<String>> source = new ArrayList<Future<String>>();
  268. source.add(Futures.successful("a"));
  269. source.add(Futures.successful("b"));
  270. //#reduce
  271. final ExecutionContext ec = system.dispatcher();
  272. //A sequence of Futures, in this case Strings
  273. Iterable<Future<String>> futures = source;
  274. Future<Object> resultFuture = reduce(futures,
  275. new Function2<Object, String, Object>() {
  276. public Object apply(Object r, String t) {
  277. return r + t; //Just concatenate
  278. }
  279. }, ec);
  280. resultFuture.onSuccess(new PrintResult<Object>(), system.dispatcher());
  281. //#reduce
  282. Object result = Await.result(resultFuture, Duration.create(5, SECONDS));
  283. assertEquals("ab", result);
  284. }
  285. @Test
  286. public void useSuccessfulAndFailedAndPromise() throws Exception {
  287. final ExecutionContext ec = system.dispatcher();
  288. //#successful
  289. Future<String> future = Futures.successful("Yay!");
  290. //#successful
  291. //#failed
  292. Future<String> otherFuture = Futures.failed(
  293. new IllegalArgumentException("Bang!"));
  294. //#failed
  295. //#promise
  296. Promise<String> promise = Futures.promise();
  297. Future<String> theFuture = promise.future();
  298. promise.success("hello");
  299. //#promise
  300. Object result = Await.result(future, Duration.create(5, SECONDS));
  301. assertEquals("Yay!", result);
  302. Throwable result2 = Await.result(otherFuture.failed(),
  303. Duration.create(5, SECONDS));
  304. assertEquals("Bang!", result2.getMessage());
  305. String out = Await.result(theFuture, Duration.create(5, SECONDS));
  306. assertEquals("hello", out);
  307. }
  308. @Test
  309. public void useFilter() throws Exception {
  310. //#filter
  311. final ExecutionContext ec = system.dispatcher();
  312. Future<Integer> future1 = Futures.successful(4);
  313. Future<Integer> successfulFilter = future1.filter(Filter.filterOf(
  314. new Function<Integer, Boolean>() {
  315. public Boolean apply(Integer i) {
  316. return i % 2 == 0;
  317. }
  318. }), ec);
  319. Future<Integer> failedFilter = future1.filter(Filter.filterOf(
  320. new Function<Integer, Boolean>() {
  321. public Boolean apply(Integer i) {
  322. return i % 2 != 0;
  323. }
  324. }), ec);
  325. //When filter fails, the returned Future will be failed with a scala.MatchError
  326. //#filter
  327. }
  328. public void sendToTheInternetz(String s) {
  329. }
  330. public void sendToIssueTracker(Throwable t) {
  331. }
  332. @Test
  333. public void useAndThen() {
  334. //#and-then
  335. final ExecutionContext ec = system.dispatcher();
  336. Future<String> future1 = Futures.successful("value").andThen(
  337. new OnComplete<String>() {
  338. public void onComplete(Throwable failure, String result) {
  339. if (failure != null)
  340. sendToIssueTracker(failure);
  341. }
  342. }, ec).andThen(new OnComplete<String>() {
  343. public void onComplete(Throwable failure, String result) {
  344. if (result != null)
  345. sendToTheInternetz(result);
  346. }
  347. }, ec);
  348. //#and-then
  349. }
  350. @Test
  351. public void useRecover() throws Exception {
  352. //#recover
  353. final ExecutionContext ec = system.dispatcher();
  354. Future<Integer> future = future(new Callable<Integer>() {
  355. public Integer call() {
  356. return 1 / 0;
  357. }
  358. }, ec).recover(new Recover<Integer>() {
  359. public Integer recover(Throwable problem) throws Throwable {
  360. if (problem instanceof ArithmeticException)
  361. return 0;
  362. else
  363. throw problem;
  364. }
  365. }, ec);
  366. future.onSuccess(new PrintResult<Integer>(), system.dispatcher());
  367. //#recover
  368. int result = Await.result(future, Duration.create(5, SECONDS));
  369. assertEquals(result, 0);
  370. }
  371. @Test
  372. public void useTryRecover() throws Exception {
  373. //#try-recover
  374. final ExecutionContext ec = system.dispatcher();
  375. Future<Integer> future = future(new Callable<Integer>() {
  376. public Integer call() {
  377. return 1 / 0;
  378. }
  379. }, ec).recoverWith(new Recover<Future<Integer>>() {
  380. public Future<Integer> recover(Throwable problem) throws Throwable {
  381. if (problem instanceof ArithmeticException) {
  382. return future(new Callable<Integer>() {
  383. public Integer call() {
  384. return 0;
  385. }
  386. }, ec);
  387. } else
  388. throw problem;
  389. }
  390. }, ec);
  391. future.onSuccess(new PrintResult<Integer>(), system.dispatcher());
  392. //#try-recover
  393. int result = Await.result(future, Duration.create(5, SECONDS));
  394. assertEquals(result, 0);
  395. }
  396. @Test
  397. public void useOnSuccessOnFailureAndOnComplete() throws Exception {
  398. {
  399. Future<String> future = Futures.successful("foo");
  400. //#onSuccess
  401. final ExecutionContext ec = system.dispatcher();
  402. future.onSuccess(new OnSuccess<String>() {
  403. public void onSuccess(String result) {
  404. if ("bar" == result) {
  405. //Do something if it resulted in "bar"
  406. } else {
  407. //Do something if it was some other String
  408. }
  409. }
  410. }, ec);
  411. //#onSuccess
  412. }
  413. {
  414. Future<String> future = Futures.failed(new IllegalStateException("OHNOES"));
  415. //#onFailure
  416. final ExecutionContext ec = system.dispatcher();
  417. future.onFailure(new OnFailure() {
  418. public void onFailure(Throwable failure) {
  419. if (failure instanceof IllegalStateException) {
  420. //Do something if it was this particular failure
  421. } else {
  422. //Do something if it was some other failure
  423. }
  424. }
  425. }, ec);
  426. //#onFailure
  427. }
  428. {
  429. Future<String> future = Futures.successful("foo");
  430. //#onComplete
  431. final ExecutionContext ec = system.dispatcher();
  432. future.onComplete(new OnComplete<String>() {
  433. public void onComplete(Throwable failure, String result) {
  434. if (failure != null) {
  435. //We got a failure, handle it here
  436. } else {
  437. // We got a result, do something with it
  438. }
  439. }
  440. }, ec);
  441. //#onComplete
  442. }
  443. }
  444. @Test
  445. public void useOrAndZip() throws Exception {
  446. {
  447. //#zip
  448. final ExecutionContext ec = system.dispatcher();
  449. Future<String> future1 = Futures.successful("foo");
  450. Future<String> future2 = Futures.successful("bar");
  451. Future<String> future3 = future1.zip(future2).map(
  452. new Mapper<scala.Tuple2<String, String>, String>() {
  453. public String apply(scala.Tuple2<String, String> zipped) {
  454. return zipped._1() + " " + zipped._2();
  455. }
  456. }, ec);
  457. future3.onSuccess(new PrintResult<String>(), system.dispatcher());
  458. //#zip
  459. String result = Await.result(future3, Duration.create(5, SECONDS));
  460. assertEquals("foo bar", result);
  461. }
  462. {
  463. //#fallback-to
  464. Future<String> future1 = Futures.failed(new IllegalStateException("OHNOES1"));
  465. Future<String> future2 = Futures.failed(new IllegalStateException("OHNOES2"));
  466. Future<String> future3 = Futures.successful("bar");
  467. // Will have "bar" in this case
  468. Future<String> future4 = future1.fallbackTo(future2).fallbackTo(future3);
  469. future4.onSuccess(new PrintResult<String>(), system.dispatcher());
  470. //#fallback-to
  471. String result = Await.result(future4, Duration.create(5, SECONDS));
  472. assertEquals("bar", result);
  473. }
  474. }
  475. @Test(expected = IllegalStateException.class)
  476. @SuppressWarnings("unchecked")
  477. public void useAfter() throws Exception {
  478. //#after
  479. final ExecutionContext ec = system.dispatcher();
  480. Future<String> failExc = Futures.failed(new IllegalStateException("OHNOES1"));
  481. Future<String> delayed = Patterns.after(Duration.create(200, "millis"),
  482. system.scheduler(), ec, failExc);
  483. Future<String> future = future(new Callable<String>() {
  484. public String call() throws InterruptedException {
  485. Thread.sleep(1000);
  486. return "foo";
  487. }
  488. }, ec);
  489. Future<String> result = Futures.firstCompletedOf(
  490. Arrays.<Future<String>>asList(future, delayed), ec);
  491. //#after
  492. Await.result(result, Duration.create(2, SECONDS));
  493. }
  494. public static class MyActor extends UntypedActor {
  495. public void onReceive(Object message) {
  496. if (message instanceof String) {
  497. getSender().tell(((String) message).toUpperCase(), getSelf());
  498. } else if (message instanceof Integer) {
  499. int i = ((Integer) message).intValue();
  500. if (i < 0) {
  501. getSender().tell(new Failure(new ArithmeticException("Negative values not supported")), getSelf());
  502. } else {
  503. getSender().tell(i, getSelf());
  504. }
  505. } else {
  506. unhandled(message);
  507. }
  508. }
  509. }
  510. }