forked from vert-x/vert-x.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
core_manual_scala.html
2632 lines (2518 loc) · 174 KB
/
core_manual_scala.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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<link href='http://fonts.googleapis.com/css?family=Lato' rel='stylesheet' type='text/css'>
<!-- <link rel="stylesheet/less" href="bootstrap/less/bootstrap.less">
<script src="bootstrap/less/less-1.3.3.min.js"></script>
-->
<link href="bootstrap/bootstrap.css" type="text/css" rel="stylesheet"/>
<link href="google-code-prettify/prettify.css" type="text/css" rel="stylesheet"/>
<script type="text/javascript" src="google-code-prettify/prettify.js"></script>
<link href="css/vertx.css" type="text/css" rel="stylesheet"/>
<link href="css/sunburst.css" type="text/css" rel="stylesheet"/>
<title>Vert.x</title>
<script>
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-30144458-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body onload="prettyPrint()" class="hp">
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse"
data-target=".nav-collapse">
<span class="i-bar"></span>
<span class="i-bar"></span>
<span class="i-bar"></span>
</a>
<a class="brand" href="/">Vert.x</a>
<div class="nav-collapse">
<ul class="nav">
<li><a href="/">Home</a></li>
<li><a href="downloads.html">Download</a></li>
<li><a href="install.html">Install</a></li>
<li><a href="docs.html">Documentation</a></li>
<li><a href="examples.html">Examples</a></li>
<li><a href="community.html">Project Info</a></li>
<li><a href="https://github.com/vert-x/vert.x">Github</a></li>
<li><a href="http://modulereg.vertx.io/">Module Registry</a></li>
<li><a href="http://groups.google.com/group/vertx">Google Group</a></li>
<li><a href="http://vertxproject.wordpress.com/">Blog</a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span12">
<div class="well">
<h1>Scala API Manual</h1>
</div>
</div>
</div>
<div class="row">
<div class="span12">
<div class="well">
<div>
<div class="toc">
<ul>
<li><a href="#writing-verticles">Writing Verticles</a><ul>
<li><a href="#asynchronous-start">Asynchronous start</a></li>
<li><a href="#verticle-clean-up">Verticle clean-up</a></li>
<li><a href="#the-container-object">The container object</a></li>
<li><a href="#the-vertx-object">The vertx object</a></li>
<li><a href="#getting-configuration-in-a-verticle">Getting Configuration in a Verticle</a></li>
<li><a href="#logging-from-a-verticle">Logging from a Verticle</a></li>
<li><a href="#accessing-environment-variables-from-a-verticle">Accessing environment variables from a Verticle</a></li>
<li><a href="#causing-the-container-to-exit">Causing the container to exit</a></li>
</ul>
</li>
<li><a href="#deploying-and-undeploying-verticles-programmatically">Deploying and Undeploying Verticles Programmatically</a><ul>
<li><a href="#deploying-a-simple-verticle">Deploying a simple verticle</a></li>
<li><a href="#deploying-worker-verticles">Deploying Worker Verticles</a></li>
<li><a href="#deploying-a-module-programmatically">Deploying a module programmatically</a></li>
<li><a href="#passing-configuration-to-a-verticle-programmatically">Passing configuration to a verticle programmatically</a></li>
<li><a href="#using-a-verticle-to-co-ordinate-loading-of-an-application">Using a Verticle to co-ordinate loading of an application</a></li>
<li><a href="#specifying-number-of-instances">Specifying number of instances</a></li>
<li><a href="#getting-notified-when-deployment-is-complete">Getting Notified when Deployment is complete</a></li>
<li><a href="#undeploying-a-verticle-or-module">Undeploying a Verticle or Module</a></li>
</ul>
</li>
<li><a href="#scaling-your-application">Scaling your application</a></li>
<li><a href="#the-event-bus">The Event Bus</a><ul>
<li><a href="#the-theory">The Theory</a><ul>
<li><a href="#addressing">Addressing</a></li>
<li><a href="#handlers">Handlers</a></li>
<li><a href="#publish-subscribe-messaging">Publish / subscribe messaging</a></li>
<li><a href="#point-to-point-and-request-response-messaging">Point to point and Request-Response messaging</a></li>
<li><a href="#transient">Transient</a></li>
<li><a href="#types-of-messages">Types of messages</a></li>
</ul>
</li>
<li><a href="#event-bus-api">Event Bus API</a><ul>
<li><a href="#registering-and-unregistering-handlers">Registering and Unregistering Handlers</a></li>
<li><a href="#publishing-messages">Publishing messages</a></li>
<li><a href="#sending-messages">Sending messages</a></li>
<li><a href="#replying-to-messages">Replying to messages</a><ul>
<li><a href="#specifying-timeouts-for-replies">Specifying timeouts for replies</a></li>
<li><a href="#getting-notified-of-reply-failures">Getting notified of reply failures</a></li>
</ul>
</li>
<li><a href="#message-types">Message types</a></li>
</ul>
</li>
<li><a href="#distributed-event-bus">Distributed event bus</a></li>
</ul>
</li>
<li><a href="#shared-data">Shared Data</a><ul>
<li><a href="#shared-maps">Shared Maps</a></li>
<li><a href="#shared-sets">Shared Sets</a></li>
</ul>
</li>
<li><a href="#buffers">Buffers</a><ul>
<li><a href="#creating-buffers">Creating Buffers</a></li>
<li><a href="#writing-to-a-buffer">Writing to a Buffer</a><ul>
<li><a href="#appending-to-a-buffer">Appending to a Buffer</a></li>
<li><a href="#random-access-buffer-writes">Random access buffer writes</a></li>
</ul>
</li>
<li><a href="#reading-from-a-buffer">Reading from a Buffer</a></li>
<li><a href="#other-buffer-methods">Other buffer methods:</a></li>
</ul>
</li>
<li><a href="#json">JSON</a></li>
<li><a href="#delayed-and-periodic-tasks">Delayed and Periodic Tasks</a><ul>
<li><a href="#one-shot-timers">One-shot Timers</a></li>
<li><a href="#periodic-timers">Periodic Timers</a></li>
<li><a href="#cancelling-timers">Cancelling timers</a></li>
</ul>
</li>
<li><a href="#writing-tcp-servers-and-clients">Writing TCP Servers and Clients</a><ul>
<li><a href="#net-server">Net Server</a><ul>
<li><a href="#creating-a-net-server">Creating a Net Server</a></li>
<li><a href="#start-the-server-listening">Start the Server Listening</a></li>
<li><a href="#getting-notified-of-incoming-connections">Getting Notified of Incoming Connections</a></li>
<li><a href="#closing-a-net-server">Closing a Net Server</a></li>
<li><a href="#netserver-properties">NetServer Properties</a></li>
<li><a href="#handling-data">Handling Data</a><ul>
<li><a href="#reading-data-from-the-socket">Reading Data from the Socket</a></li>
<li><a href="#writing-data-to-a-socket">Writing Data to a Socket</a></li>
</ul>
</li>
<li><a href="#socket-remote-address">Socket Remote Address</a></li>
<li><a href="#socket-local-address">Socket Local Address</a></li>
<li><a href="#closing-a-socket">Closing a socket</a></li>
<li><a href="#closed-handler">Closed Handler</a></li>
<li><a href="#exception-handler">Exception handler</a></li>
<li><a href="#event-bus-write-handler">Event Bus Write Handler</a></li>
<li><a href="#read-and-write-streams">Read and Write Streams</a></li>
</ul>
</li>
<li><a href="#scaling-tcp-servers">Scaling TCP Servers</a></li>
<li><a href="#netclient">NetClient</a><ul>
<li><a href="#creating-a-net-client">Creating a Net Client</a></li>
<li><a href="#making-a-connection">Making a Connection</a></li>
<li><a href="#configuring-reconnection">Configuring Reconnection</a></li>
<li><a href="#netclient-properties">NetClient Properties</a></li>
</ul>
</li>
<li><a href="#ssl-servers">SSL Servers</a></li>
<li><a href="#ssl-clients">SSL Clients</a></li>
</ul>
</li>
<li><a href="#flow-control-streams-and-pumps">Flow Control - Streams and Pumps</a><ul>
<li><a href="#readstream">ReadStream</a></li>
<li><a href="#writestream">WriteStream</a></li>
<li><a href="#pump">Pump</a></li>
</ul>
</li>
<li><a href="#writing-http-servers-and-clients">Writing HTTP Servers and Clients</a><ul>
<li><a href="#writing-http-servers">Writing HTTP servers</a><ul>
<li><a href="#creating-an-http-server">Creating an HTTP Server</a></li>
<li><a href="#start-the-server-listening_1">Start the Server Listening</a></li>
<li><a href="#getting-notified-of-incoming-requests">Getting Notified of Incoming Requests</a></li>
<li><a href="#handling-http-requests">Handling HTTP Requests</a><ul>
<li><a href="#request-method">Request Method</a></li>
<li><a href="#request-version">Request Version</a></li>
<li><a href="#request-uri">Request URI</a></li>
<li><a href="#request-path">Request Path</a></li>
<li><a href="#request-query">Request Query</a></li>
<li><a href="#request-headers">Request Headers</a></li>
<li><a href="#request-params">Request params</a></li>
<li><a href="#remote-address">Remote Address</a></li>
<li><a href="#absolute-uri">Absolute URI</a></li>
<li><a href="#reading-data-from-the-request-body">Reading Data from the Request Body</a></li>
<li><a href="#handling-multipart-form-uploads">Handling Multipart Form Uploads</a></li>
<li><a href="#handling-multipart-form-attributes">Handling Multipart Form Attributes</a></li>
</ul>
</li>
<li><a href="#http-server-responses">HTTP Server Responses</a></li>
<li><a href="#setting-status-code-and-message">Setting Status Code and Message</a><ul>
<li><a href="#writing-http-responses">Writing HTTP responses</a></li>
<li><a href="#ending-http-responses">Ending HTTP responses</a></li>
<li><a href="#closing-the-underlying-connection">Closing the underlying connection</a></li>
<li><a href="#response-headers">Response headers</a></li>
<li><a href="#chunked-http-responses-and-trailers">Chunked HTTP Responses and Trailers</a></li>
</ul>
</li>
<li><a href="#serving-files-directly-from-disk">Serving files directly from disk</a></li>
<li><a href="#pumping-responses">Pumping Responses</a></li>
<li><a href="#http-compression">HTTP Compression</a></li>
</ul>
</li>
<li><a href="#writing-http-clients">Writing HTTP Clients</a><ul>
<li><a href="#creating-an-http-client">Creating an HTTP Client</a></li>
<li><a href="#pooling-and-keep-alive">Pooling and Keep Alive</a></li>
<li><a href="#closing-the-client">Closing the client</a></li>
<li><a href="#making-requests">Making Requests</a><ul>
<li><a href="#handling-exceptions">Handling exceptions</a></li>
<li><a href="#writing-to-the-request-body">Writing to the request body</a></li>
<li><a href="#ending-http-requests">Ending HTTP requests</a></li>
<li><a href="#writing-request-headers">Writing Request Headers</a></li>
<li><a href="#request-timeouts">Request timeouts</a></li>
<li><a href="#http-chunked-requests">HTTP chunked requests</a></li>
</ul>
</li>
<li><a href="#http-client-responses">HTTP Client Responses</a><ul>
<li><a href="#reading-data-from-the-response-body">Reading Data from the Response Body</a></li>
<li><a href="#reading-cookies">Reading cookies</a></li>
</ul>
</li>
<li><a href="#100-continue-handling">100-Continue Handling</a></li>
<li><a href="#http-compression_1">HTTP Compression</a></li>
</ul>
</li>
<li><a href="#pumping-requests-and-responses">Pumping Requests and Responses</a></li>
<li><a href="#https-servers">HTTPS Servers</a></li>
<li><a href="#https-clients">HTTPS Clients</a></li>
<li><a href="#scaling-http-servers">Scaling HTTP servers</a></li>
</ul>
</li>
<li><a href="#routing-http-requests-with-pattern-matching">Routing HTTP requests with Pattern Matching</a><ul>
<li><a href="#specifying-matches">Specifying matches.</a></li>
<li><a href="#extracting-parameters-from-the-path">Extracting parameters from the path</a></li>
<li><a href="#extracting-params-using-regular-expressions">Extracting params using Regular Expressions</a></li>
<li><a href="#handling-requests-where-nothing-matches">Handling requests where nothing matches</a></li>
</ul>
</li>
<li><a href="#websockets">WebSockets</a><ul>
<li><a href="#websockets-on-the-server">WebSockets on the server</a><ul>
<li><a href="#reading-from-and-writing-to-websockets">Reading from and Writing to WebSockets</a></li>
<li><a href="#rejecting-websockets">Rejecting WebSockets</a></li>
<li><a href="#headers-on-the-websocket">Headers on the websocket</a></li>
</ul>
</li>
<li><a href="#websockets-on-the-http-client">WebSockets on the HTTP client</a></li>
<li><a href="#websockets-in-the-browser">WebSockets in the browser</a></li>
</ul>
</li>
<li><a href="#sockjs">SockJS</a><ul>
<li><a href="#sockjs-server">SockJS Server</a></li>
<li><a href="#reading-and-writing-data-from-a-sockjs-server">Reading and writing data from a SockJS server</a></li>
<li><a href="#sockjs-client">SockJS client</a></li>
</ul>
</li>
<li><a href="#sockjs-eventbus-bridge">SockJS - EventBus Bridge</a><ul>
<li><a href="#setting-up-the-bridge">Setting up the Bridge</a></li>
<li><a href="#using-the-event-bus-from-client-side-javascript">Using the Event Bus from client side JavaScript</a></li>
<li><a href="#securing-the-bridge">Securing the Bridge</a></li>
<li><a href="#messages-that-require-authorisation">Messages that require authorisation</a></li>
</ul>
</li>
<li><a href="#file-system">File System</a><ul>
<li><a href="#synchronous-forms">Synchronous forms</a></li>
<li><a href="#copy">copy</a></li>
<li><a href="#move">move</a></li>
<li><a href="#truncate">truncate</a></li>
<li><a href="#chmod">chmod</a></li>
<li><a href="#props">props</a></li>
<li><a href="#lprops">lprops</a></li>
<li><a href="#link">link</a></li>
<li><a href="#symlink">symlink</a></li>
<li><a href="#unlink">unlink</a></li>
<li><a href="#readsymlink">readSymLink</a></li>
<li><a href="#delete">delete</a></li>
<li><a href="#mkdir">mkdir</a></li>
<li><a href="#readdir">readDir</a></li>
<li><a href="#readfile">readFile</a></li>
<li><a href="#writefile">writeFile</a></li>
<li><a href="#createfile">createFile</a></li>
<li><a href="#exists">exists</a></li>
<li><a href="#fsprops">fsProps</a></li>
<li><a href="#open">open</a></li>
<li><a href="#asyncfile">AsyncFile</a><ul>
<li><a href="#random-access-writes">Random access writes</a></li>
<li><a href="#random-access-reads">Random access reads</a></li>
<li><a href="#flushing-data-to-underlying-storage">Flushing data to underlying storage.</a></li>
<li><a href="#using-asyncfile-as-readstream-and-writestream">Using AsyncFile as ReadStream and WriteStream</a></li>
<li><a href="#closing-an-asyncfile">Closing an AsyncFile</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#dns-client-work-in-progress-useable-in-lang-scala-version-030">DNS Client (Work in Progress, useable in lang-scala version 0.3.0)</a><ul>
<li><a href="#lookup">lookup</a></li>
<li><a href="#lookup4">lookup4</a></li>
<li><a href="#lookup6">lookup6</a></li>
<li><a href="#resolvea">resolveA</a></li>
<li><a href="#resolveaaaa">resolveAAAA</a></li>
<li><a href="#resolvecname">resolveCNAME</a></li>
<li><a href="#resolvemx">resolveMX</a></li>
<li><a href="#resolvetxt">resolveTXT</a></li>
<li><a href="#resolvens">resolveNS</a></li>
<li><a href="#resolvesrv">resolveSRV</a></li>
<li><a href="#resolveptr">resolvePTR</a></li>
<li><a href="#reverselookup">reverseLookup</a></li>
<li><a href="#error-handling">Error handling</a><ul>
<li><a href="#noerror">NOERROR</a></li>
<li><a href="#formerror">FORMERROR</a></li>
<li><a href="#servfail">SERVFAIL</a></li>
<li><a href="#nxdomain">NXDOMAIN</a></li>
<li><a href="#notimpl">NOTIMPL</a></li>
<li><a href="#refused">REFUSED</a></li>
<li><a href="#yxdomain">YXDOMAIN</a></li>
<li><a href="#yxrrset">YXRRSET</a></li>
<li><a href="#nxrrset">NXRRSET</a></li>
<li><a href="#notzone">NOTZONE</a></li>
<li><a href="#badver">BADVER</a></li>
<li><a href="#badsig">BADSIG</a></li>
<li><a href="#badkey">BADKEY</a></li>
<li><a href="#badtime">BADTIME</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<h1 id="writing-verticles">Writing Verticles</h1><br/>
<p>As was described in the <a href="manual.html#verticle">main manual</a>, a verticle is the execution unit of Vert.x.</p>
<p>To recap, Vert.x is a container which executes packages of code called Verticles, and it ensures that the code in the verticle is never executed concurrently by more than one thread. You can write your verticles in any of the languages that Vert.x supports, and Vert.x supports running many verticle instances concurrently in the same Vert.x instance.</p>
<p>All the code you write in a Vert.x application runs inside a Verticle instance.</p>
<p>For simple prototyping and trivial tasks you can write raw verticles and run them directly on the command line, but in most cases you will always wrap your verticles inside Vert.x <a href="mods_manual.html">modules</a>.</p>
<p>For now, let's try writing a simple raw verticle.</p>
<p>As an example we'll write a simple TCP echo server. The server just accepts connections and any data received by it is echoed back on the connection.</p>
<p>Copy the following into a text editor and save it as <code>Server.scala</code></p>
<pre class="prettyprint">import org.vertx.scala.core.net.NetSocket
import org.vertx.scala.core.streams.Pump
vertx.createNetServer().connectHandler({ socket: NetSocket =>
Pump.createPump(socket, socket).start
}).listen(1234)
</pre>
<p>Now run it:</p>
<pre class="prettyprint">vertx run Server.scala
</pre>
<p>The server will now be running. Connect to it using telnet:</p>
<pre class="prettyprint">telnet localhost 1234
</pre>
<p>And notice how data you send (and hit enter) is echoed back to you. </p>
<p>Congratulations! You've written your first verticle.</p>
<p>Notice how you didn't have to first compile the <code>.scala</code> file to a <code>.class</code> file. Vert.x understands how to run <code>.scala</code> files directly - internally doing the compilation on the fly. (It also supports running .class files too if you prefer) </p>
<p>Just as in Java, you can also write classes that extend Verticle like this:</p>
<pre class="prettyprint">import org.vertx.scala.core.net.NetSocket
import org.vertx.scala.core.streams.Pump
import org.vertx.scala.platform.Verticle
class Server extends Verticle {
override def start() {
vertx.createNetServer().connectHandler({ socket: NetSocket =>
Pump.createPump(socket, socket).start
}).listen(1234)
}
}
</pre>
<p>Running this works the same way as the script before.</p>
<p>Every Scala verticle must extend the class <code>org.vertx.scala.platform.Verticle</code>. You must override the <code>start</code> method - this is called by Vert.x when the verticle is started.</p>
<p><em>In the rest of this manual we'll assume the code snippets are running inside a verticle.</em></p>
<h2 id="asynchronous-start">Asynchronous start</h2><br/>
<p>In some cases your Verticle has to do some other stuff asynchronously in its <code>start()</code> method, e.g. start other verticles, and the verticle shouldn't be considered started until those other actions are complete.</p>
<p>If this is the case for your verticle you can implement the asynchronous version of the <code>start()</code> method:</p>
<pre class="prettyprint">override def start(startedResult: Promise[Unit]) {
// For example - deploy some other verticle
container.deployVerticle("foo.js", Json.obj(), 1, { deployResult: AsyncResult[String] =>
if (deployResult.succeeded()) {
startedResult.success(deployResult.result())
} else {
startedResult.failure(deployResult.cause())
}
})
}
</pre>
<p>If you overwrite both <code>start</code> methods, the synchronous version (without parameters) gets called before the asynchronous version (with Promise[Unit] parameter).</p>
<p>For the AsyncResult[_] you can also use a helper methode like this:</p>
<pre class="prettyprint">implicit def tryToAsyncResultHandler[X](tryHandler: Try[X] => Unit): AsyncResult[X] => Unit = {
tryHandler.compose { ar: AsyncResult[X] =>
if (ar.succeeded()) {
Success(ar.result())
} else {
Failure(ar.cause())
}
}
}
</pre>
<p>And than you can use pattern matching with Try[_] like this:</p>
<pre class="prettyprint">override def start(startedResult: Promise[Unit]) {
container.deployVerticle("foo.js", Json.obj(), 1, {
case Success(result) => startedResult.success(result)
case Failure(x) => startedResult.failure(x)
}: Try[String] => Unit)
}
</pre>
<h2 id="verticle-clean-up">Verticle clean-up</h2><br/>
<p>Servers, clients, event bus handlers and timers will be automatically closed / cancelled when the verticle is stopped. However, if you have any other clean-up logic that you want to execute when the verticle is stopped, you can implement a <code>stop</code> method which will be called when the verticle is undeployed. </p>
<h2 id="the-container-object">The <code>container</code> object</h2><br/>
<p>Each verticle instance has a member variable called <code>container</code>. This represents the Verticle's view of the container in which it is running.</p>
<p>The container object contains methods for deploying and undeploying verticle and modules, and also allows config, environment variables and a logger to be accessed.</p>
<h2 id="the-vertx-object">The <code>vertx</code> object</h2><br/>
<p>Each verticle instance has a member variable called <code>vertx</code>. This provides access to the Vert.x core API. You'll use the Core API to do most things in Vert.x including TCP, HTTP, file system access, event bus, timers etc.</p>
<h2 id="getting-configuration-in-a-verticle">Getting Configuration in a Verticle</h2><br/>
<p>You can pass configuration to a module or verticle from the command line using the <code>-conf</code> option, for example:</p>
<pre class="prettyprint">vertx runmod com.mycompany~my-mod~1.0 -conf myconf.json
</pre>
<p>or for a raw verticle</p>
<pre class="prettyprint">vertx run foo.js -conf myconf.json
</pre>
<p>The argument to <code>-conf</code> is the name of a text file containing a valid JSON object.</p>
<p>That configuration is available inside your verticle by calling the <code>config()</code> method on the <code>container</code> member variable of the verticle:</p>
<pre class="prettyprint">val config: JsonObject = container.config()
println("Config is " + config)
</pre>
<p>The config returned is an instance of <code>org.vertx.scala.core.json.Json</code>, which is a class which represents JSON objects (unsurprisingly!). You can use this object to configure the verticle.</p>
<p>Allowing verticles to be configured in a consistent way like this allows configuration to be easily passed to them irrespective of the language that deploys the verticle.</p>
<h2 id="logging-from-a-verticle">Logging from a Verticle</h2><br/>
<p>Each verticle is given its own logger. To get a reference to it invoke the <code>logger()</code> method on the container instance:</p>
<pre class="prettyprint">val logger = container.logger()
logger.info("I am logging something")
</pre>
<p>The logger is an instance of the class <code>org.vertx.scala.core.logging.Logger</code> and has the following methods;</p>
<ul>
<li>trace</li>
<li>debug</li>
<li>info</li>
<li>warn</li>
<li>error</li>
<li>fatal </li>
</ul>
<p>Which have the normal meanings you would expect.</p>
<p>The log files by default go in a file called <code>vertx.log</code> in the system temp directory. On my Linux box this is <code>\tmp</code>.</p>
<p>For more information on configuring logging, please see the <a href="manual.html#logging">main manual</a>.</p>
<h2 id="accessing-environment-variables-from-a-verticle">Accessing environment variables from a Verticle</h2><br/>
<p>You can access the map of environment variables from a Verticle with the <code>env()</code> method on the <code>container</code> object.</p>
<h2 id="causing-the-container-to-exit">Causing the container to exit</h2><br/>
<p>You can call the <code>exit()</code> method of the container to cause the Vert.x instance to make a clean shutdown.</p>
<h1 id="deploying-and-undeploying-verticles-programmatically">Deploying and Undeploying Verticles Programmatically</h1><br/>
<p>You can deploy and undeploy verticles programmatically from inside another verticle. Any verticles deployed this way will be able to see resources (classes, scripts, other files) of the main verticle.</p>
<h2 id="deploying-a-simple-verticle">Deploying a simple verticle</h2><br/>
<p>To deploy a verticle programmatically call the function <code>deployVerticle</code> on the <code>container</code> variable. </p>
<p>To deploy a single instance of a verticle :</p>
<pre class="prettyprint">container.deployVerticle(main)
</pre>
<p>Where <code>main</code> is the name of the Verticle (i.e. the name of the script or FQCN of the class).</p>
<p>See the chapter on <a href="manual.html#running-vertx">"running Vert.x"</a> in the main manual for a description of what a main is.</p>
<h2 id="deploying-worker-verticles">Deploying Worker Verticles</h2><br/>
<p>The <code>deployVerticle</code> method deploys standard (non worker) verticles. If you want to deploy worker verticles use the <code>deployWorkerVerticle</code> method. This method takes the same parameters as <code>deployVerticle</code> with the same meanings.</p>
<h2 id="deploying-a-module-programmatically">Deploying a module programmatically</h2><br/>
<p>You should use <code>deployModule</code> to deploy a module, for example:</p>
<pre class="prettyprint">container.deployModule("io.vertx~mod-mailer~2.0.0-beta1", config)
</pre>
<p>Would deploy an instance of the <code>io.vertx~mod-mailer~2.0.0-beta1</code> module with the specified configuration. Please see the <a href="">modules manual</a> for more information about modules.</p>
<h2 id="passing-configuration-to-a-verticle-programmatically">Passing configuration to a verticle programmatically</h2><br/>
<p>JSON configuration can be passed to a verticle that is deployed programmatically. Inside the deployed verticle the configuration is accessed with the <code>config()</code> method. For example:</p>
<pre class="prettyprint">val config = Json.obj("foo" -> "wibble", "bar" -> false)
container.deployVerticle("foo.ChildVerticle", config)
</pre>
<p>Then, in <code>ChildVerticle</code> you can access the config via <code>config()</code> as previously explained.</p>
<h2 id="using-a-verticle-to-co-ordinate-loading-of-an-application">Using a Verticle to co-ordinate loading of an application</h2><br/>
<p>If you have an appplication that is composed of multiple verticles that all need to be started at application start-up, then you can use another verticle that maintains the application configuration and starts all the other verticles. You can think of this as your application starter verticle.</p>
<p>For example, you could create a verticle <code>AppStarter</code> as follows:</p>
<pre class="prettyprint">// Application config
val appConfig: JsonObject = container.config()
val verticle1Config = appConfig.getObject("verticle1_conf")
val verticle2Config = appConfig.getObject("verticle2_conf")
val verticle3Config = appConfig.getObject("verticle3_conf")
val verticle4Config = appConfig.getObject("verticle4_conf")
val verticle5Config = appConfig.getObject("verticle5_conf")
// Start the verticles that make up the app
container.deployVerticle("verticle1.js", verticle1Config)
container.deployVerticle("verticle2.rb", verticle2Config)
container.deployVerticle("foo.Verticle3", verticle3Config)
container.deployWorkerVerticle("foo.Verticle4", verticle4Config)
container.deployWorkerVerticle("verticle5.js", verticle5Config, 10)
</pre>
<p>Then create a file 'config.json" with the actual JSON config in it</p>
<pre class="prettyprint">{
"verticle1_conf": {
"foo": "wibble"
},
"verticle2_conf": {
"age": 1234,
"shoe_size": 12,
"pi": 3.14159
},
"verticle3_conf": {
"strange": true
},
"verticle4_conf": {
"name": "george"
},
"verticle5_conf": {
"tel_no": "123123123"
}
}
</pre>
<p>Then set the <code>AppStarter</code> as the main of your module and then you can start your entire application by simply running:</p>
<pre class="prettyprint">vertx runmod com.mycompany~my-mod~1.0 -conf config.json
</pre>
<p>If your application is large and actually composed of multiple modules rather than verticles you can use the same technique.</p>
<p>More commonly you'd probably choose to write your starter verticle in a scripting language such as JavaScript, Groovy, Ruby or Python - these languages have much better JSON support than Scala, so you can maintain the whole JSON config nicely in the starter verticle itself.</p>
<h2 id="specifying-number-of-instances">Specifying number of instances</h2><br/>
<p>By default, when you deploy a verticle only one instance of the verticle is deployed. Verticles instances are strictly single threaded so this means you will use at most one core on your server.</p>
<p>Vert.x scales by deploying many verticle instances concurrently.</p>
<p>If you want more than one instance of a particular verticle or module to be deployed, you can specify the number of instances as follows:</p>
<pre class="prettyprint">container.deployVerticle("foo.ChildVerticle", 10)
</pre>
<p>Or</p>
<pre class="prettyprint">container.deployModule("io.vertx~some-mod~1.0", 10)
</pre>
<p>The above examples would deploy 10 instances.</p>
<h2 id="getting-notified-when-deployment-is-complete">Getting Notified when Deployment is complete</h2><br/>
<p>The actual verticle deployment is asynchronous and might not complete until some time after the call to <code>deployVerticle</code> or <code>deployModule</code> has returned. If you want to be notified when the verticle has completed being deployed, you can pass a handler as the final argument to <code>deployVerticle</code> or <code>deployModule</code>:</p>
<pre class="prettyprint">container.deployVerticle("foo.ChildVerticle", Json.obj(), 1, { asyncResult: AsyncResult[String] =>
if (asyncResult.succeeded()) {
println("The verticle has been deployed, deployment ID is " + asyncResult.result())
} else {
asyncResult.cause().printStackTrace()
}
})
</pre>
<p>The handler will get passed an instance of <code>AsyncResult</code> when it completes. You can use the methods <code>succeeded()</code> and <code>failed()</code> on <code>AsyncResult</code> to see if the operation completed ok.</p>
<p>The method <code>result()</code> provides the result of the async operation (if any) which in this case is the deployment ID - you will need this if you need to subsequently undeploy the verticle / module.</p>
<p>The method <code>cause()</code> provides the <code>Throwable</code> if the action failed.</p>
<h2 id="undeploying-a-verticle-or-module">Undeploying a Verticle or Module</h2><br/>
<p>Any verticles or modules that you deploy programmatically from within a verticle, and all of their children are automatically undeployed when the parent verticle is undeployed, so in many cases you will not need to undeploy a verticle manually, however if you do need to do this, it can be done by calling the method <code>undeployVerticle</code> or <code>undeployModule</code> passing in the deployment id. </p>
<pre class="prettyprint">container.undeployVerticle(deploymentID)
</pre>
<p>You can also provide a handler to the undeploy method if you want to be informed when undeployment is complete.</p>
<h1 id="scaling-your-application">Scaling your application</h1><br/>
<p>A verticle instance is almost always single threaded (the only exception is multi-threaded worker verticles which are an advanced feature), this means a single instance can at most utilise one core of your server.</p>
<p>In order to scale across cores you need to deploy more verticle instances. The exact numbers depend on your application - how many verticles there are and of what type.</p>
<p>You can deploy more verticle instances programmatically or on the command line when deploying your module using the <code>-instances</code> command line option.</p>
<p><a id="event-bus"> </a> </p>
<h1 id="the-event-bus">The Event Bus</h1><br/>
<p>The event bus is the nervous system of Vert.x.</p>
<p>It allows verticles to communicate with each other irrespective of what language they are written in, and whether they're in the same Vert.x instance, or in a different Vert.x instance.</p>
<p>It even allows client side JavaScript running in a browser to communicate on the same event bus. (More on that later).</p>
<p>The event bus forms a distributed peer-to-peer messaging system spanning multiple server nodes and multiple browsers.</p>
<p>The event bus API is incredibly simple. It basically involves registering handlers, unregistering handlers and sending and publishing messages.</p>
<p>First some theory:</p>
<h2 id="the-theory">The Theory</h2><br/>
<h3 id="addressing">Addressing</h3><br/>
<p>Messages are sent on the event bus to an <em>address</em>.</p>
<p>Vert.x doesn't bother with any fancy addressing schemes. In Vert.x an address is simply a string, any string is valid. However it is wise to use some kind of scheme, e.g. using periods to demarcate a namespace.</p>
<p>Some examples of valid addresses are <code>europe.news.feed1</code>, <code>acme.games.pacman</code>, <code>sausages</code>, and <code>X</code>.</p>
<h3 id="handlers">Handlers</h3><br/>
<p>A handler is a thing that receives messages from the bus. You register a handler at an address.</p>
<p>Many different handlers from the same or different verticles can be registered at the same address. A single handler can be registered by the verticle at many different addresses.</p>
<h3 id="publish-subscribe-messaging">Publish / subscribe messaging</h3><br/>
<p>The event bus supports <em>publishing</em> messages. Messages are published to an address. Publishing means delivering the message to all handlers that are registered at that address. This is the familiar <em>publish/subscribe</em> messaging pattern.</p>
<h3 id="point-to-point-and-request-response-messaging">Point to point and Request-Response messaging</h3><br/>
<p>The event bus supports <em>point to point</em> messaging. Messages are sent to an address. Vert.x will then route it to just one of the handlers registered at that address. If there is more than one handler registered at the address, one will be chosen using a non-strict round-robin algorithm.</p>
<p>With point to point messaging, an optional reply handler can be specified when sending the message. When a message is received by a recipient, and has been handled, the recipient can optionally decide to reply to the message. If they do so that reply handler will be called.</p>
<p>When the reply is received back at the sender, it too can be replied to. This can be repeated ad-infinitum, and allows a dialog to be set-up between two different verticles. This is a common messaging pattern called the <em>Request-Response</em> pattern.</p>
<h3 id="transient">Transient</h3><br/>
<p><em>All messages in the event bus are transient, and in case of failure of all or parts of the event bus, there is a possibility messages will be lost. If your application cares about lost messages, you should code your handlers to be idempotent, and your senders to retry after recovery.</em></p>
<p>If you want to persist your messages you can use a persistent work queue module for that.</p>
<h3 id="types-of-messages">Types of messages</h3><br/>
<p>Messages that you send on the event bus can be as simple as a string, a number or a boolean. You can also send Vert.x buffers or JSON messages.</p>
<p>It's highly recommended you use JSON messages to communicate between verticles. JSON is easy to create and parse in all the languages that Vert.x supports.</p>
<h2 id="event-bus-api">Event Bus API</h2><br/>
<p>Let's jump into the API.</p>
<h3 id="registering-and-unregistering-handlers">Registering and Unregistering Handlers</h3><br/>
<p>To set a message handler on the address <code>test.address</code>, you do something like the following:</p>
<pre class="prettyprint">val eb = vertx.eventBus
val myHandler = { message: Message[_] =>
println("I received a message " + message.body)
}
eb.registerHandler("test.address", myHandler)
</pre>
<p>It's as simple as that. The handler will then receive any messages sent to that address.</p>
<p>The class <code>Message</code> is a generic type and specific Message types include <code>Message[Boolean]</code>, <code>Message[Buffer]</code>, <code>Message[Array[Byte]]</code>, <code>Message[Byte]</code>, <code>Message[Character]</code>, <code>Message[Double]</code>, <code>Message[Float]</code>, <code>Message[Integer]</code>, <code>Message[JsonObject]</code>, <code>Message[JsonArray]</code>, <code>Message[Long]</code>, <code>Message[Short]</code> and <code>Message[String]</code>.</p>
<p>If you know you'll always be receiving messages of a particular type you can use the specific type in your handler, e.g:</p>
<pre class="prettyprint">val myHandler = { message: Message[String] =>
val body: String = message.body
}
</pre>
<p>The return value of <code>registerHandler</code> is the Event Bus itself, i.e. we provide a <em>fluent</em> API so you can chain multiple calls together. </p>
<p>When you register a handler on an address and you're in a cluster it can take some time for the knowledge of that new handler to be propagated across the entire cluster. If you want to be notified when that has completed you can optionally specify another handler to the <code>registerHandler</code> method as the third argument. This handler will then be called once the information has reached all nodes of the cluster. E.g. :</p>
<pre class="prettyprint">eb.registerHandler("test.address", myHandler, { asyncResult: AsyncResult[Void] =>
println("The handler has been registered across the cluster ok? " + asyncResult.succeeded())
})
</pre>
<p>To unregister a handler it's just as straightforward. You simply call <code>unregisterHandler</code> passing in the address and the handler:</p>
<pre class="prettyprint">eb.unregisterHandler("test.address", myHandler)
</pre>
<p>Current issue for the unregisterHandler: The event bus currently uses anonymous functions as handlers. The implicit conversion of the functions to handlers is causing "unregisterHandler" not to work, as a new Handler[Message[X]] is created from the anonymous function every time.</p>
<p>A single handler can be registered multiple times on the same, or different, addresses so in order to identify it uniquely you have to specify both the address and the handler.</p>
<p>As with registering, when you unregister a handler and you're in a cluster it can also take some time for the knowledge of that unregistration to be propagated across the entire to cluster. If you want to be notified when that has completed you can optionally specify another function to the registerHandler as the third argument. E.g. :</p>
<pre class="prettyprint">eb.unregisterHandler("test.address", myHandler, { asyncResult: AsyncResult[Void] =>
println("The handler has been unregistered across the cluster ok? " + asyncResult.succeeded())
})
</pre>
<p>If you want your handler to live for the full lifetime of your verticle there is no need to unregister it explicitly - Vert.x will automatically unregister any handlers when the verticle is stopped.</p>
<h3 id="publishing-messages">Publishing messages</h3><br/>
<p>Publishing a message is also trivially easy. Just publish it specifying the address, for example:</p>
<pre class="prettyprint">eb.publish("test.address", "hello world")
</pre>
<p>That message will then be delivered to all handlers registered against the address "test.address".</p>
<h3 id="sending-messages">Sending messages</h3><br/>
<p>Sending a message will result in only one handler registered at the address receiving the message. This is the point to point messaging pattern. The handler is chosen in a non strict round-robin fashion.</p>
<pre class="prettyprint">eb.send("test.address", "hello world")
</pre>
<h3 id="replying-to-messages">Replying to messages</h3><br/>
<p>Sometimes after you send a message you want to receive a reply from the recipient. This is known as the <em>request-response pattern</em>.</p>
<p>To do this you send a message, and specify a reply handler as the third argument. When the receiver receives the message they can reply to it by calling the <code>reply</code> method on the message.. When this method is invoked it causes a reply to be sent back to the sender where the reply handler is invoked. An example will make this clear:</p>
<p>The receiver:</p>
<pre class="prettyprint">val myHandler = { message: Message[String] =>
println("I received a message " + message.body)
// Do some stuff
// Now reply to it
message.reply("This is a reply")
}
eb.registerHandler("test.address", myHandler)
</pre>
<p>The sender:</p>
<pre class="prettyprint">eb.send("test.address", "This is a message", { message: Message[String] =>
println("I received a reply " + message.body)
})
</pre>
<p>It is legal also to send an empty reply or a null reply.</p>
<p>The replies themselves can also be replied to so you can create a dialog between two different verticles consisting of multiple rounds.</p>
<h4 id="specifying-timeouts-for-replies">Specifying timeouts for replies</h4><br/>
<p>If you send a message specifying a reply handler, and the reply never comes, then, by default, you'll be left with a handler that never gets unregistered.</p>
<p>To remedy this you can also specify a <code>AsyncResult[Message] => Unit</code> as a reply handler and a timeout in ms. If a reply is received before timeout your handler will be called with an <code>AsyncResult</code> containing the message, but if no reply is received before timeout, the handler will be automatically unregistered and your handler will be called with a failed result so you can deal with it in your code.</p>
<p>Here's an example:</p>
<pre class="prettyprint">eb.sendWithTimeout("test.address", "This is a message", 1000, { ar: AsyncResult[Message[String]] =>
if (ar.succeeded()) {
println("I received a reply " + ar.result.body)
} else {
println("No reply was received before the 1 second timeout!")
}
})
</pre>
<p>If the send times out, the exception it is available with the <code>cause()</code> method of the <code>AsyncResult</code> is of type <code>ReplyException</code>. The return value <code>failureType()</code> on the <code>ReplyException</code> instance is <code>ReplyFailure.TIMEOUT</code>.</p>
<p>You can also set a default timeout on the event bus itself - this timeout will be used if you are using the <code>send(...)</code> method on the event bus to send messages with a reply handler. The default value of the default timeout is <code>-1</code> which means that reply handlers will never timeout (this is for backward compatibility reasons with earlier versions of Vert.x).</p>
<pre class="prettyprint">eb.setDefaultReplyTimeout(5000)
eb.send("test.address", "This is a message", { msg: Message[String] =>
println("I received a reply before the timeout of 5 seconds")
})
</pre>
<p>When replying to messages you can also provide a timeout and a <code>Handler<AsyncResult<Message>></code> to get replies to the replies within a timeout. The API used is similar to before:</p>
<pre class="prettyprint">message.replyWithTimeout("This is a reply", 1000, { ar: AsyncResult[Message[String]] =>
if (ar.succeeded()) {
println("I received a reply to the reply" + ar.result.body)
} else {
println("No reply to the reply was received before the 1 second timeout!")
}
})
</pre>
<h4 id="getting-notified-of-reply-failures">Getting notified of reply failures</h4><br/>
<p>If you send a message with a timeout and result handler, and there are no handlers available to send the message to, the handler will be called with a failed <code>AsyncResult</code> where the <code>cause()</code> is a <code>ReplyException</code>. The return value <code>failureType()</code> on the <code>ReplyException</code> instance is <code>ReplyFailure.NO_HANDLERS</code>.</p>
<p>If you send a message with a timeout and result handler, and the recipent of the message responds by calling <code>Message.fail(..)</code>, the handler will be called with a failed <code>AsyncResult</code> where the <code>cause()</code> is a <code>ReplyException</code>. The return value <code>failureType()</code> on the <code>ReplyException</code> instance is <code>ReplyFailure.RECIPIENT_FAILURE</code>.</p>
<p>For example</p>
<pre class="prettyprint">eb.registerHandler("test.address", { message: Message[String] =>
message.fail(123, "Not enough aardvarks")
})
eb.sendWithTimeout("test.address", "This is a message", 1000, { ar: AsyncResult[Message[String]] =>
if (ar.succeeded()) {
println("I received a reply " + ar.result().body)
} else {
val ex = result.cause().asInstanceOf[ReplyException]
println("Failure type: " + ex.failureType())
println("Failure code: " + ex.failureCode())
println("Failure message: " + ex.message())
}
})
</pre>
<h3 id="message-types">Message types</h3><br/>
<p>The message you send can be any of the following types (or their matching boxed type):</p>
<ul>
<li>Boolean</li>
<li>Array[Byte]</li>
<li>Byte</li>
<li>Char</li>
<li>Double</li>
<li>Float</li>
<li>Int</li>
<li>Long</li>
<li>Short</li>
<li>String</li>
<li>org.vertx.scala.core.json.JsonObject</li>
<li>org.vertx.scala.core.json.JsonArray</li>
<li>org.vertx.scala.core.buffer.Buffer</li>
</ul>
<p>Vert.x buffers and JSON objects and arrays are copied before delivery if they are delivered in the same JVM, so different verticles can't access the exact same object instance which could lead to race conditions.</p>
<p>Here are some more examples:</p>
<p>Send some numbers:</p>
<pre class="prettyprint">eb.send("test.address", 1234)
eb.send("test.address", 3.14159)
</pre>
<p>Send a boolean:</p>
<pre class="prettyprint">eb.send("test.address", true)
</pre>
<p>Send a JSON object:</p>
<pre class="prettyprint">val obj = Json.obj("foo" -> "wibble")
eb.send("test.address", obj)
</pre>
<p>Null messages can also be sent:</p>
<pre class="prettyprint">eb.send("test.address", null)
</pre>
<p>It's a good convention to have your verticles communicating using JSON - this is because JSON is easy to generate and parse for all the languages that Vert.x supports.</p>
<h2 id="distributed-event-bus">Distributed event bus</h2><br/>
<p>To make each Vert.x instance on your network participate on the same event bus, start each Vert.x instance with the <code>-cluster</code> command line switch.</p>
<p>See the chapter in the main manual on <a href=""><em>running Vert.x</em></a> for more information on this. </p>
<p>Once you've done that, any Vert.x instances started in cluster mode will merge to form a distributed event bus. </p>
<h1 id="shared-data">Shared Data</h1><br/>
<p>Sometimes it makes sense to allow different verticles instances to share data in a safe way. Vert.x allows simple <code>java.util.concurrent.ConcurrentMap</code> and <code>java.util.Set</code> data structures to be shared between verticles.</p>
<p>There is a caveat: To prevent issues due to mutable data, Vert.x only allows simple immutable types such as number, boolean and string or Buffer to be used in shared data. With a Buffer, it is automatically copied when retrieved from the shared data, so different verticle instances never see the same object instance.</p>
<p>Currently data can only be shared between verticles in the <em>same Vert.x instance</em>. In later versions of Vert.x we aim to extend this to allow data to be shared by all Vert.x instances in the cluster.</p>
<h2 id="shared-maps">Shared Maps</h2><br/>
<p>To use a shared map to share data between verticles first we get a reference to the map, and then use it like any other instance of <code>java.util.concurrent.ConcurrentMap</code></p>
<pre class="prettyprint">val map: ConcurrentMap[String, Integer] = vertx.sharedData.getMap("demo.mymap")
map.put("some-key", 123)
</pre>
<p>And then, in a different verticle you can access it:</p>
<pre class="prettyprint">val map = vertx.sharedData.getMap("demo.mymap")
// etc
</pre>
<p>To get the information in it use:</p>
<pre class="prettyprint">map.get("some-key")
</pre>
<h2 id="shared-sets">Shared Sets</h2><br/>
<p>To use a shared set to share data between verticles first we get a reference to the set.</p>
<pre class="prettyprint">val set = vertx.sharedData.getSet("demo.myset")
set.add("some-value")
</pre>
<p>And then, in a different verticle:</p>
<pre class="prettyprint">val set = vertx.sharedData.getSet("demo.myset")
// etc
</pre>
<p>To get it use:</p>
<pre class="prettyprint"> val itr = set.iterator()
while(itr.hasNext()) {
val info = itr.next()
}
</pre>
<h1 id="buffers">Buffers</h1><br/>
<p>Most data in Vert.x is shuffled around using instances of <code>org.vertx.scala.core.buffer.Buffer</code>.</p>
<p>A Buffer represents a sequence of zero or more bytes that can be written to or read from, and which expands automatically as necessary to accomodate any bytes written to it. You can perhaps think of a buffer as smart byte array.</p>
<h2 id="creating-buffers">Creating Buffers</h2><br/>
<p>Create a new empty buffer:</p>
<pre class="prettyprint">val buff = Buffer()
</pre>
<p>Create a buffer from a String. The String will be encoded in the buffer using UTF-8.</p>
<pre class="prettyprint">val buff = Buffer("some-string")
</pre>
<p>Create a buffer from a String: The String will be encoded using the specified encoding, e.g:</p>
<pre class="prettyprint">val buff = Buffer("some-string", "UTF-16")
</pre>
<p>Create a buffer from a byte[]</p>
<pre class="prettyprint">val bytes = Array[Byte](...)
Buffer(bytes)
</pre>
<p>Create a buffer with an initial size hint. If you know your buffer will have a certain amount of data written to it you can create the buffer and specify this size. This makes the buffer initially allocate that much memory and is more efficient than the buffer automatically resizing multiple times as data is written to it.</p>
<p>Note that buffers created this way <em>are empty</em>. It does not create a buffer filled with zeros up to the specified size.</p>
<pre class="prettyprint">val buff = Buffer(100000)
</pre>
<h2 id="writing-to-a-buffer">Writing to a Buffer</h2><br/>
<p>There are two ways to write to a buffer: appending, and random access. In either case buffers will always expand automatically to encompass the bytes. It's not possible to get an <code>IndexOutOfBoundsException</code> with a buffer.</p>
<h3 id="appending-to-a-buffer">Appending to a Buffer</h3><br/>
<p>To append to a buffer, you use the <code>appendXXX</code> methods. Append methods exist for appending other buffers, Array[Byte], String and all primitive types.</p>
<p>The return value of the <code>appendXXX</code> methods is the buffer itself, so these can be chained:</p>
<pre class="prettyprint">val buff = Buffer()
buff.appendInt(123).appendString("hello").appendChar('\n')
socket.write(buff)
</pre>
<h3 id="random-access-buffer-writes">Random access buffer writes</h3><br/>
<p>You can also write into the buffer at a specific index, by using the <code>setXXX</code> methods. Set methods exist for other buffers, Array[Byte], String and all primitive types. All the set methods take an index as the first argument - this represents the position in the buffer where to start writing the data.</p>
<p>The buffer will always expand as necessary to accomodate the data.</p>
<pre class="prettyprint">val buff = Buffer()
buff.setInt(1000, 123)
buff.setBytes(0, Array[Byte](...))
</pre>
<h2 id="reading-from-a-buffer">Reading from a Buffer</h2><br/>
<p>Data is read from a buffer using the <code>getXXX</code> methods. Get methods exist for Array[Byte], String and all primitive types. The first argument to these methods is an index in the buffer from where to get the data.</p>
<pre class="prettyprint">val buff = ...
for (i <- 0 until buff.length() by 4) {
println("int value at " + i + " is " + buff.getInt(i))
}
</pre>
<h2 id="other-buffer-methods">Other buffer methods:</h2><br/>
<ul>
<li><code>length()</code>. To obtain the length of the buffer. The length of a buffer is the index of the byte in the buffer with the largest index + 1.</li>
<li><code>copy()</code>. Copy the entire buffer</li>
</ul>
<p>See the JavaDoc for more detailed method level documentation. </p>
<h1 id="json">JSON</h1><br/>
<p>Whereas JavaScript has first class support for JSON, and Ruby has Hash literals which make representing JSON easy within code, things aren't so easy in Scala.</p>
<p>For this reason, if you want to use JSON from within your Scala verticles, we provide some simple JSON classes which represent a JSON object and a JSON array. These classes provide methods for setting and getting all types supported in JSON on an object or array.</p>
<p>A JSON object is represented by instances of <code>org.vertx.scala.core.json.JsonObject</code>. A JSON array is represented by instances of <code>org.vertx.scala.core.json.JsonArray</code>.</p>
<p>A usage example would be using a Scala verticle to send or receive JSON messages from the event bus.</p>
<pre class="prettyprint">val eb = vertx.eventBus
val obj = Json.obj("foo" -> "wibble", "age" -> 1000)
eb.send("some-address", obj)
// ....
// And in a handler somewhere:
def handle(message: Message[JsonObject]) = {
println("foo is " + message.body.getString("foo"))
println("age is " + message.body.getNumber("age"))
}
</pre>
<p>Methods also existing for converting this objects to and from their JSON serialized forms. </p>
<h1 id="delayed-and-periodic-tasks">Delayed and Periodic Tasks</h1><br/>
<p>It's very common in Vert.x to want to perform an action after a delay, or periodically.</p>
<p>In standard verticles you can't just make the thread sleep to introduce a delay, as that will block the event loop thread.</p>
<p>Instead you use Vert.x timers. Timers can be <em>one-shot</em> or <em>periodic</em>. We'll discuss both</p>
<h2 id="one-shot-timers">One-shot Timers</h2><br/>
<p>A one shot timer calls an event handler after a certain delay, expressed in milliseconds. </p>
<p>To set a timer to fire once you use the <code>setTimer</code> method passing in the delay and a handler</p>
<pre class="prettyprint">val timerID = vertx.setTimer(1000, { timerID: Long =>
logger.info("And one second later this is printed")
})
logger.info("First this is printed")
</pre>
<p>The return value is a unique timer id which can later be used to cancel the timer. The handler is also passed the timer id.</p>
<h2 id="periodic-timers">Periodic Timers</h2><br/>
<p>You can also set a timer to fire periodically by using the <code>setPeriodic</code> method. There will be an initial delay equal to the period. The return value of <code>setPeriodic</code> is a unique timer id (long). This can be later used if the timer needs to be cancelled. The argument passed into the timer event handler is also the unique timer id:</p>
<pre class="prettyprint">val timerID = vertx.setPeriodic(1000, { timerID: Long =>
logger.info("And every second this is printed")
})
logger.info("First this is printed")
</pre>
<h2 id="cancelling-timers">Cancelling timers</h2><br/>
<p>To cancel a periodic timer, call the <code>cancelTimer</code> method specifying the timer id. For example:</p>
<pre class="prettyprint">val timerID = vertx.setPeriodic(1000, { timerID: Long => })
// And immediately cancel it
vertx.cancelTimer(timerID)
</pre>
<p>Or you can cancel it from inside the event handler. The following example cancels the timer after it has fired 10 times.</p>
<pre class="prettyprint">var count: Int = 0
val timerID = vertx.setPeriodic(1000, { timerID: Long =>
logger.info("In event handler " + count)
count = count + 1
if (count == 10) {
vertx.cancelTimer(timerID)
}
})
</pre>
<h1 id="writing-tcp-servers-and-clients">Writing TCP Servers and Clients</h1><br/>
<p>Creating TCP servers and clients is very easy with Vert.x.</p>
<h2 id="net-server">Net Server</h2><br/>
<h3 id="creating-a-net-server">Creating a Net Server</h3><br/>
<p>To create a TCP server you call the <code>createNetServer</code> method on your <code>vertx</code> instance.</p>
<pre class="prettyprint">val server = vertx.createNetServer()
</pre>
<h3 id="start-the-server-listening">Start the Server Listening</h3><br/>
<p>To tell that server to listen for connections we do: </p>
<pre class="prettyprint">vertx.createNetServer.listen(1234, "myhost")
</pre>
<p>The first parameter to <code>listen</code> is the port. A wildcard port of <code>0</code> can be specified which means a random available port will be chosen to actually listen at. Once the server has completed listening you can then call the <code>port()</code> method of the server to find out the real port it is using.</p>
<p>The second parameter is the hostname or ip address. If it is omitted it will default to <code>0.0.0.0</code> which means it will listen at all available interfaces.</p>
<p>The actual bind is asynchronous so the server might not actually be listening until some time <em>after</em> the call to listen has returned. If you want to be notified when the server is actually listening you can provide a handler to the <code>listen</code> call. For example:</p>
<pre class="prettyprint">server.listen(1234, "myhost", { asyncResult: AsyncResult[NetServer] =>
logger.info("Listen succeeded? " + asyncResult.succeeded())
})
</pre>
<h3 id="getting-notified-of-incoming-connections">Getting Notified of Incoming Connections</h3><br/>
<p>To be notified when a connection occurs we need to call the <code>connectHandler</code> method of the server, passing in a handler. The handler will then be called when a connection is made:</p>
<pre class="prettyprint">vertx.createNetServer.connectHandler({ sock: NetSocket =>
logger.info("A client has connected!")
})
server.listen(1234, "localhost")
</pre>
<p>That's a bit more interesting. Now it displays 'A client has connected!' every time a client connects. </p>
<p>The return value of the <code>connectHandler</code> method is the server itself, so multiple invocations can be chained together. That means we can rewrite the above as:</p>
<pre class="prettyprint">val server = vertx.createNetServer()
server.connectHandler({ sock: NetSocket =>
logger.info("A client has connected!")
}).listen(1234, "localhost")
</pre>
<p>or </p>
<pre class="prettyprint">vertx.createNetServer().connectHandler({ sock: NetSocket =>
logger.info("A client has connected!")
}).listen(1234, "localhost")
</pre>
<p>This is a common pattern throughout the Vert.x API. </p>
<h3 id="closing-a-net-server">Closing a Net Server</h3><br/>
<p>To close a net server just call the <code>close</code> function.</p>
<pre class="prettyprint">server.close()
</pre>
<p>The close is actually asynchronous and might not complete until some time after the <code>close</code> method has returned. If you want to be notified when the actual close has completed then you can pass in a handler to the <code>close</code> method.</p>
<p>This handler will then be called when the close has fully completed.</p>
<pre class="prettyprint">server.close({ asyncResult: AsyncResult[Void] =>
log.info("Close succeeded? " + asyncResult.succeeded())
})
</pre>
<p>If you want your net server to last the entire lifetime of your verticle, you don't need to call <code>close</code> explicitly, the Vert.x container will automatically close any servers that you created when the verticle is undeployed. </p>
<h3 id="netserver-properties">NetServer Properties</h3><br/>
<p>NetServer has a set of properties you can set which affect its behaviour. Firstly there are bunch of properties used to tweak the TCP parameters, in most cases you won't need to set these:</p>
<ul>
<li>
<p><code>setTCPNoDelay(tcpNoDelay)</code> If true then <a href="http://en.wikipedia.org/wiki/Nagle's_algorithm">Nagle's Algorithm</a> is disabled. If false then it is enabled.</p>
</li>
<li>
<p><code>setSendBufferSize(size)</code> Sets the TCP send buffer size in bytes.</p>
</li>
<li>
<p><code>setReceiveBufferSize(size)</code> Sets the TCP receive buffer size in bytes.</p>
</li>
<li>
<p><code>setTCPKeepAlive(keepAlive)</code> if <code>keepAlive</code> is true then <a href="http://en.wikipedia.org/wiki/Keepalive#TCP_keepalive">TCP keep alive</a> is enabled, if false it is disabled. </p>
</li>
<li>
<p><code>setReuseAddress(reuse)</code> if <code>reuse</code> is true then addresses in TIME_WAIT state can be reused after they have been closed.</p>
</li>
<li>
<p><code>setSoLinger(linger)</code></p>
</li>
<li>
<p><code>setTrafficClass(trafficClass)</code></p>
</li>
</ul>
<p>NetServer has a further set of properties which are used to configure SSL. We'll discuss those later on.</p>
<h3 id="handling-data">Handling Data</h3><br/>
<p>So far we have seen how to create a NetServer, and accept incoming connections, but not how to do anything interesting with the connections. Let's remedy that now.</p>
<p>When a connection is made, the connect handler is called passing in an instance of <code>NetSocket</code>. This is a socket-like interface to the actual connection, and allows you to read and write data as well as do various other things like close the socket.</p>
<h4 id="reading-data-from-the-socket">Reading Data from the Socket</h4><br/>
<p>To read data from the socket you need to set the <code>dataHandler</code> on the socket. This handler will be called with an instance of <code>org.vertx.scala.core.buffer.Buffer</code> every time data is received on the socket. You could try the following code and telnet to it to send some data:</p>
<pre class="prettyprint">vertx.createNetServer.connectHandler({ sock: NetSocket =>
sock.dataHandler({ buffer: Buffer =>
logger.info("I received " + buffer.length() + " bytes of data")
})
}).listen(1234, "localhost")
</pre>
<h4 id="writing-data-to-a-socket">Writing Data to a Socket</h4><br/>
<p>To write data to a socket, you invoke the <code>write</code> function. This function can be invoked in a few ways:</p>
<p>With a single buffer:</p>
<pre class="prettyprint">val myBuffer = Buffer(...)
sock.write(myBuffer)
</pre>
<p>A string. In this case the string will encoded using UTF-8 and the result written to the wire.</p>
<pre class="prettyprint">sock.write("hello")
</pre>
<p>A string and an encoding. In this case the string will encoded using the specified encoding and the result written to the wire. </p>
<pre class="prettyprint">sock.write("hello", "UTF-16")
</pre>
<p>The <code>write</code> function is asynchronous and always returns immediately after the write has been queued.</p>
<p>Let's put it all together.</p>
<p>Here's an example of a simple TCP echo server which simply writes back (echoes) everything that it receives on the socket:</p>
<pre class="prettyprint">vertx.createNetServer.connectHandler({ sock: NetSocket =>
sock.dataHandler({ buffer: Buffer =>