forked from eclipse-vertx/vert.x
-
Notifications
You must be signed in to change notification settings - Fork 0
/
core_manual_java.html
2412 lines (2264 loc) · 150 KB
/
core_manual_java.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 rel="stylesheet/less" href="bootstrap/less/bootstrap.less">
<script src="less-1.2.1.min.js"></script>
<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 Java API Manual</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()">
<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 class="active"><a href="/">Home</a></li>
<li><a href="https://github.com/purplefox/vert.x/downloads">Download</a></li>
<li><a href="install.html">Install</a></li>
<li><a href="tutorials.html">Tutorials</a></li>
<li><a href="examples.html">Examples</a></li>
<li><a href="docs.html">Documentation</a></li>
<li><a href="https://github.com/purplefox/vert.x">Source</a></li>
<li><a href="http://groups.google.com/group/vertx">Google Group</a></li>
<li><a href="community.html">Community</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 style="font-size: 35px;">Java 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="#verticle-clean-up">Verticle clean-up</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>
</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-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="#deploying-worker-verticles">Deploying Worker Verticles</a></li>
<li><a href="#undeploying-a-verticle">Undeploying a Verticle</a></li>
</ul>
</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="#sending-messages">Sending 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="#sending-messages_1">Sending messages</a></li>
<li><a href="#replying-to-messages">Replying to messages</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="#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="#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="#catching-exceptions-on-the-net-client">Catching exceptions on the Net Client</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-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="#reading-data-from-the-request-body">Reading Data from the Request Body</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>
</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="#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="#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>
</ul>
</li>
</ul>
</li>
<li><a href="#pumping-requests-and-responses">Pumping Requests and Responses</a><ul>
<li><a href="#100-continue-handling">100-Continue Handling</a></li>
</ul>
</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>
</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>
<li><a href="#routing-websockets-with-pattern-matching">Routing WebSockets with Pattern Matching</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>
</ul>
</div>
<h1 id="writing-verticles">Writing Verticles</h1><br/>
<p>We previously discussed how a verticle is the unit of deployment in vert.x. Let's look in more detail about how to write a 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.java</code></p>
<pre class="prettyprint">import org.vertx.java.core.Handler;
import org.vertx.java.core.net.NetSocket;
import org.vertx.java.core.streams.Pump;
import org.vertx.java.deploy.Verticle;
public class Server extends Verticle {
public void start() {
vertx.createNetServer().connectHandler(new Handler<NetSocket>() {
public void handle(final NetSocket socket) {
Pump.createPump(socket, socket).start();
}
}).listen(1234);
}
}
</pre>
<p>Now, go to the directory where you saved the file and compile it with:</p>
<pre class="prettyprint">javac Server.java -cp $VERTX_HOME/lib/jars/vert.x.jar
</pre>
<p><em>Where VERTX_HOME is the directory where you installed vert.x</em> <br/>
</p>
<p>Now run it:</p>
<pre class="prettyprint">vertx run Server
</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. <br/>
</p>
<p>Congratulations! You've written your first verticle.</p>
<p>Every Java verticle must extend the class <code>org.vertx.java.deploy.Verticle</code>. You must override the <code>start</code> method - this is called by Vert.x when the verticle is started.</p>
<h2 id="verticle-clean-up">Verticle clean-up</h2><br/>
<p>Servers, clients and event bus handlers will be automatically closed 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="getting-configuration-in-a-verticle">Getting Configuration in a Verticle</h2><br/>
<p>If JSON configuration has been passed when deploying a verticle from either the command line using <code>vertx run</code> or <code>vertx deploy</code> and specifying a configuration file, or when deploying programmatically, that configuration is available by calling the <code>getConfig</code> method on the <code>container</code> member variable of the verticle:</p>
<pre class="prettyprint">JsonObject config = container.getConfig();
System.out.println("Config is " + config);
</pre>
<p>The config returned is an instance of <code>org.vertx.java.core.json.JsonObject</code>, which is a class which represents JSON objects (unsurprisingly!). You can use this object to configure the verticle. Allowing verticles to be configured in a consistent way like this allows configuration to be easily passed to them irrespective of the language.</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>getLogger</code> method on the container instance:</p>
<pre class="prettyprint">Logger logger = container.getLogger();
logger.info("I am logging something");
</pre>
<p>The logger is an instance of the class <code>org.vertx.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 <br/>
</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 main manual.</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 programmatically inherit the path of the parent 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. The return value of <code>deployVerticle</code> is the unique id of the deployment, which can be used later to undeploy the verticle.</p>
<p>To deploy a single instance of a verticle :</p>
<pre class="prettyprint">String id = container.deployVerticle(main);
</pre>
<p>Where <code>main</code> is the name of the "main" of the Verticle (i.e. the name of the script if it's a Ruby or JavaScript verticle or the fully qualified class name if it's a Java verticle). See the chapter on "running vert.x" in the main manual for a description of what a main is.</p>
<h2 id="deploying-a-module-programmatically">Deploying a module programmatically</h2><br/>
<p>You can also use <code>deployVerticle</code> to deploy an installed module, for example:</p>
<pre class="prettyprint">container.deployVerticle("mailer", config);
</pre>
<p>Would deploy an instance of the out-of-the-box mailer module (see the modules manual) with the specified configuration.<br/>
</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>getConfig</code> method. For example:</p>
<pre class="prettyprint">JsonObject config = new JsonObject();
config.putString("foo", "wibble");
config.putBoolean("bar", false);
container.deployVerticle("foo.ChildVerticle", config);
</pre>
<p>Then, in <code>ChildVerticle</code> you can access the config via <code>getConfig</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
JsonObject appConfig = container.getConfig();
JsonObject verticle1Config = appConfig.getObject("verticle1_conf");
JsonObject verticle2Config = appConfig.getObject("verticle2_conf");
JsonObject verticle3Config = appConfig.getObject("verticle3_conf");
JsonObject verticle4Config = appConfig.getObject("verticle4_conf");
JsonObject 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 (see main manual on configuring verticles):</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 you can start your entire application by simply running:</p>
<pre class="prettyprint">vertx run app.js -conf config.json
</pre>
<p>or</p>
<pre class="prettyprint">vertx deploy app.js -conf config.json
</pre>
<p>See the chapter on running vert.x in the main manual for more information on this. <br/>
</p>
<p>Alternatively, even if you choose to write your main verticles in Java, you could maintain a single JavaScript verticle as an app starter - JavaScript has much better JSON support than Java, so you can maintain the whole JSON config nicely in the verticle itself. Take a look at the JavaScript core guide to see how to do that.</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. If you want more than one instance to be deployed, e.g. so you can scale over your cores better, you can specify the number of instances as follows:</p>
<pre class="prettyprint">container.deployVerticle("foo.ChildVerticle", 10);
</pre>
<p>The above example 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> 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>:</p>
<pre class="prettyprint">container.deployVerticle("foo.ChildVerticle", 10, new SimpleHandler() {
public void handle() {
System.out.println("The verticle has been deployed");
}
});
</pre>
<p>The handler is an instance of <code>org.vertx.java.core.Handler<Void></code>. <code>org.vertx.java.core.SimpleHandler</code> is a convenience class which implements this interface. <br/>
</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="undeploying-a-verticle">Undeploying a Verticle</h2><br/>
<p>Any verticles that you deploy programmatically from within a verticle, and all of their children are automatically undeployed when the parent verticle is undeployed, so in most cases you will not need to undeploy a verticle manually, however if you do want to do this, it can be done by calling the function <code>undeployVerticle</code> passing in the deployment id that was returned from the call to <code>deployVerticle</code></p>
<pre class="prettyprint">String deploymentID = container.deployVerticle(main);
container.undeployVerticle(deploymentID);
</pre>
<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. It even allows client side JavaScript running in a browser to communicate on the same event bus. (More on that later).</p>
<p>It creates a distributed polyglot overlay network 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 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>The handler will receive any messages that are sent to the address. 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>
<p>Since many handlers can subscribe to the address, this is an implementation of the messaging pattern called <em>Publish-Subscribe Messaging</em>.</p>
<p>When a message is received in a handler, and has been <em>processed</em>, the receiver can optionally decide to reply to the message. If they do so, and the message was sent specifying a reply handler, 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.</p>
<p>This is a common messaging pattern called the <em>Request-Response</em> pattern.</p>
<h3 id="sending-messages">Sending messages</h3><br/>
<p>You send a message by specifying the address and telling the event bus to send it there. The event bus will then deliver the message to any handlers registered at that address.</p>
<p>If multiple vert.x instances are clustered together, the message will be delivered to any matching handlers irrespective of what vert.x instance they reside on.<br/>
</p>
<p>As previously mentioned, when sending a message you can specify an optional reply handler which will be invoked once the message has reached a handler and the recipient has replied to it.</p>
<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 busmod for that.</p>
<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 the following:</p>
<pre class="prettyprint">EventBus eb = vertx.eventBus();
Handler<Message> myHandler = new Handler<Message>() {
public void handle(Message message) {
System.out.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<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<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">Handler<Message<String>> myHandler = new Handler<Message<String>() {
public void handle(Message<String> message) {
String body = message.body;
}
};
</pre>
<p>The return value of <code>registerHandler</code> is a unique id for the handler that you can later use when unregistering, if you like. <br/>
</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, new SimpleHandler() {
public void handle() {
System.out.println("The handler has been registered across the cluster");
}
});
</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>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>Alternatively, can unregister a handler using a unique id that was returned from the call to <code>registerHandler</code>. </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, new SimpleHandler() {
public void handle() {
System.out.println("The handler has been unregistered across the cluster");
}
});
</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. <br/>
</p>
<h3 id="sending-messages_1">Sending messages</h3><br/>
<p>Sending a message is also trivially easy. Just send it specifying the address you want to send it to, for example:</p>
<pre class="prettyprint">eb.send("test.address", "hello world");
</pre>
<p>That message will then be delivered to any handlers registered against the address "test.address". If you are running vert.x in cluster mode then it will also be delivered to any handlers on that address irrespective of what vert.x instance they are in.</p>
<p>The message you send can be any of the following types (or their matching boxed type):</p>
<ul>
<li>boolean</li>
<li>byte[]</li>
<li>byte</li>
<li>char</li>
<li>double</li>
<li>float</li>
<li>int</li>
<li>long</li>
<li>short</li>
<li>java.lang.String</li>
<li>org.vertx.java.core.json.JsonObject</li>
<li>org.vertx.java.core.buffer.Buffer</li>
</ul>
<p>Vert.x buffers and JSON objects are copied before delivery if they are delivered in the same JVM, so different verticles can't access the exact same object instance.</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">JsonObject obj = new JsonObject();
obj.putString("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.</p>
<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">Handler<Message<String>> myHandler = new Handler<Message<String>>() {
public void handle(Message<String> message) {
System.out.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", new Handler<Message<String>>() {
public void handle(Message<String> message) {
System.out.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>
<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 <em>running vert.x</em> 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. <br/>
</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">ConcurrentMap<String, Integer> map = 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">ConcurrentMap<String, Integer> map = vertx.sharedData().getMap('demo.mymap');
// etc
</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">Set<String> set = vertx.sharedData().getSet('demo.myset');
set.add("some-value");
</pre>
<p>And then, in a different verticle:</p>
<pre class="prettyprint">Set<String> set = vertx.sharedData().getSet('demo.myset');
// etc
</pre>
<h1 id="buffers">Buffers</h1><br/>
<p>Most data in vert.x is shuffled around using instances of <code>org.vertx.java.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">Buffer buff = new Buffer();
</pre>
<p>Create a buffer from a String. The String will be encoded in the buffer using UTF-8.</p>
<pre class="prettyprint">Buffer buff = new 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">Buffer buff = new Buffer("some-string", "UTF-16");
</pre>
<p>Create a buffer from a byte[]</p>
<pre class="prettyprint">byte[] bytes = new byte[] { ... };
new 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">Buffer buff = new 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, 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">Buffer buff = new Buffer();
buff.appendInt(123).appendString("hello").appendChar('\n');
socket.writeBuffer(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, 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">Buffer buff = new Buffer();
buff.setInt(1000, 123);
buff.setBytes(0, "hello");
</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 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">Buffer buff = ...;
for (int i = 0; i < buff.length(); i += 4) {
System.out.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. <br/>
</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 Java.</p>
<p>For this reason, if you want to use JSON from within your Java 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.java.core.json.JsonObject</code>. A JSON array is represented by instances of <code>org.vertx.java.core.json.JsonArray</code>.</p>
<p>A usage example would be using a Java verticle to send or receive JSON messages from the event bus.</p>
<pre class="prettyprint">EventBus eb = vertx.eventBus();
JsonObject obj = new JsonObject().setString("foo", "wibble")
.setNumber("age", 1000);
eb.send("some-address", obj);
// ....
// And in a handler somewhere:
public void handle(Message<JsonObject> message) {
System.out.println("foo is " + message.body.getString("foo");
System.out.println("age is " + message.body.getNumber("age");
}
</pre>
<p>Methods also existing for converting this objects to and from their JSON serialized forms.<br/>
</p>
<p>Please see the JavaDoc for the full Java Json API. <br/>
</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">vertx.setTimer(1000, new Handler<Long>() {
public void handle(Long timerID) {
log.info('And one second later this is printed');
}
});
log.info('First this is printed');
</pre>
<p>The handler is passed the unique id for the timer. <br/>
</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">long timerID = vertx.setPeriodic(1000, new Handler<Long>() {
public void handle(Long timerID) {
log.info('And every second this is printed');
}
});
log.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">long timerID = vertx.setPeriodic(1000, new Handler<Long>() {
public void handle(Long timerID) {
}
});
// 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">long timerID = vertx.setPeriodic(1000, new Handler<Long>() {
int count;
public void handle(Long timerID) {
log.info("In event handler " + count);
count++;
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 incredibly 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 vertx instance.</p>
<pre class="prettyprint">NetServer 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: <br/>
</p>
<pre class="prettyprint">NetServer server = vertx.createNetServer();
server.listen(1234, "myhost");
</pre>
<p>The first parameter to <code>listen</code> is the port. The second parameter is the hostname or ip address. If it is ommitted it will default to <code>0.0.0.0</code> which means it will listen at all available interfaces.</p>
<h3 id="getting-notified-of-incoming-connections">Getting Notified of Incoming Connections</h3><br/>
<p>Just having a TCP server listening creates a working server that you can connect to (try it with telnet!), however it's not very useful since it doesn't do anything with the connections.</p>
<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 be called when a connection is made:</p>
<pre class="prettyprint">NetServer server = vertx.createNetServer();
server.connectHandler(new Handler<NetSocket>() {
public void handle(NetSocket sock) {
log.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. <br/>
</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">NetServer server = vertx.createNetServer();
server.connectHandler(new Handler<NetSocket>() {
public void handle(NetSocket sock) {
log.info("A client has connected!");
}
}).listen(1234, "localhost");
</pre>
<p>or </p>
<pre class="prettyprint">vertx.createNetServer().connectHandler(new Handler<NetSocket>() {
public void handle(NetSocket sock) {
log.info("A client has connected!");
}
}).listen(1234, "localhost");
</pre>
<p>This is a common pattern throughout the vert.x API.<br/>
</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(new SimpleHandler() {
public void handle() {
log.info('The server is now fully closed.');
}
});
</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 stopped. <br/>
</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 <code>tcpNoDelay</code> is 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.java.core.buffer.Bufer</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">NetServer server = vertx.createNetServer();
server.connectHandler(new Handler<NetSocket>() {
public void handle(NetSocket sock) {
sock.dataHandler(new Handler<Buffer>() {
public void handle(Buffer buffer) {
log.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">Buffer myBuffer = new 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. <br/>
</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>The actual write might occur some time later. If you want to be informed when the actual write has happened you can pass in a handler as a final argument.</p>
<p>This handler will then be invoked when the write has completed:</p>
<pre class="prettyprint">sock.write('hello', new SimpleHandler() {
public void handle() {
log.info('It has actually been written');
}
});
</pre>
<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">NetServer server = vertx.createNetServer();
server.connectHandler(new Handler<NetSocket>() {
public void handle(final NetSocket sock) {
sock.dataHandler(new Handler<Buffer>() {
public void handle(Buffer buffer) {
sock.write(buffer);
}
});
}
}).listen(1234, "localhost");
</pre>
<h3 id="closing-a-socket">Closing a socket</h3><br/>
<p>You can close a socket by invoking the <code>close</code> method. This will close the underlying TCP connection.</p>
<h3 id="closed-handler">Closed Handler</h3><br/>
<p>If you want to be notified when a socket is closed, you can set the `closedHandler':</p>
<pre class="prettyprint">NetServer server = vertx.createNetServer();
server.connectHandler(new Handler<NetSocket>() {
public void handle(final NetSocket sock) {
sock.closedHandler(new SimpleHandler() {
public void handle() {
log.info("The socket is now closed");
}
});
}
}).listen(1234, "localhost");
</pre>
<p>The closed handler will be called irrespective of whether the close was initiated by the client or server.</p>
<h3 id="exception-handler">Exception handler</h3><br/>
<p>You can set an exception handler on the socket that will be called if an exception occurs:</p>
<pre class="prettyprint">NetServer server = vertx.createNetServer();
server.connectHandler(new Handler<NetSocket>() {
public void handle(final NetSocket sock) {
sock.exceptionHandler(new SimpleHandler() {
public void handle() {
log.info("Oops, something went wrong");
}
});
}
}).listen(1234, "localhost");
</pre>
<h3 id="read-and-write-streams">Read and Write Streams</h3><br/>
<p>NetSocket also implements <code>org.vertx.java.core.streams.ReadStream</code> and <code>org.vertx.java.core.streams.WriteStream</code>. This allows flow control to occur on the connection and the connection data to be pumped to and from other object such as HTTP requests and responses, websockets and asynchronous files.</p>
<p>This will be discussed in depth in the chapter on streams and pumps.</p>
<h2 id="scaling-tcp-servers">Scaling TCP Servers</h2><br/>
<p>A verticle instance is strictly single threaded.</p>
<p>If you create a simple TCP server and deploy a single instance of it then all the handlers for that server are always executed on the same event loop (thread).</p>
<p>This means that if you are running on a server with a lot of cores, and you only have this one instance deployed then you will have at most one core utilised on your server! That's not very good, right?</p>
<p>To remedy this you can simply deploy more instances of the verticle in the server, e.g.</p>
<pre class="prettyprint">vertx run foo.MyServer -instances 20
</pre>
<p>The above would run 20 instances of foo.MyServer to a locally running vert.x instance.</p>
<p>Once you do this you will find the echo server works functionally identically to before, but, <em>as if by magic</em>, all your cores on your server can be utilised and more work can be handled.</p>
<p>At this point you might be asking yourself <em>'Hold on, how can you have more than one server listening on the same host and port? Surely you will get port conflicts as soon as you try and deploy more than one instance?'</em></p>
<p><em>Vert.x does a little magic here</em>.</p>
<p>When you deploy another server on the same host and port as an existing server it doesn't actually try and create a new server listening on the same host/port.</p>
<p>Instead it internally maintains just a single server, and, as incoming connections arrive it distributes them in a round-robin fashion to any of the connect handlers set by the verticles.</p>
<p>Consequently vert.x TCP servers can scale over available cores while each vert.x verticle instance remains strictly single threaded, and you don't have to do any special tricks like writing load-balancers in order to scale your server on your multi-core machine.</p>
<h2 id="netclient">NetClient</h2><br/>
<p>A NetClient is used to make TCP connections to servers.</p>
<h3 id="creating-a-net-client">Creating a Net Client</h3><br/>
<p>To create a TCP client you call the <code>createNetClient</code> method on your vertx instance.</p>
<pre class="prettyprint">NetClient client = vertx.createNetClient();
</pre>
<h3 id="making-a-connection">Making a Connection</h3><br/>
<p>To actually connect to a server you invoke the <code>connect</code> method:</p>
<pre class="prettyprint">NetClient client = vertx.createNetClient();
client.connect(1234, "localhost", new Handler<NetSocket>() {
public void handle(NetSocket socket) {
log.info("We have connected!");
}
});
</pre>
<p>The connect method takes the port number as the first parameter, followed by the hostname or ip address of the server. The third parameter is a connect handler. This handler will be called when the connection actually occurs.</p>
<p>The argument passed into the connect handler is an instance of <code>org.vertx.java.core.net.NetSocket</code>, exactly the same as what is passed into the server side connect handler. Once given the <code>NetSocket</code> you can read and write data from the socket in exactly the same way as you do on the server side.</p>
<p>You can also close it, set the closed handler, set the exception handler and use it as a <code>ReadStream</code> or <code>WriteStream</code> exactly the same as the server side <code>NetSocket</code>.</p>
<h3 id="catching-exceptions-on-the-net-client">Catching exceptions on the Net Client</h3><br/>
<p>You can set an exception handler on the <code>NetClient</code>. This will catch any exceptions that occur during connection.</p>
<pre class="prettyprint">NetClient client = vertx.createNetClient();
client.exceptionHandler(new Handler<NetSocket>() {
public void handle(Exception ex) {
log.error("Failed to connect", ex);
}
});
client.connect(4242, "host-that-doesnt-exist", new Handler<NetSocket>() {
public void handle(NetSocket socket) {
log.info("This won't get caled");
}
});
</pre>
<h3 id="configuring-reconnection">Configuring Reconnection</h3><br/>
<p>A NetClient can be configured to automatically retry connecting or reconnecting to the server in the event that it cannot connect or has lost its connection. This is done by invoking the methods <code>setReconnectAttempts</code> and <code>setReconnectInterval</code>:</p>
<pre class="prettyprint">NetClient client = vertx.createNetClient();
client.setReconnectAttempts(1000);
client.setReconnectInterval(500);
</pre>
<p><code>ReconnectAttempts</code> determines how many times the client will try to connect to the server before giving up. A value of <code>-1</code> represents an infinite number of times. The default value is <code>0</code>. I.e. no reconnection is attempted.</p>
<p><code>ReconnectInterval</code> detemines how long, in milliseconds, the client will wait between reconnect attempts. The default value is <code>1000</code>.</p>
<p>If an exception handler is set on the client, and reconnect attempts is not equal to <code>0</code>. Then the exception handler will not be called until the client gives up reconnecting.</p>
<h3 id="netclient-properties">NetClient Properties</h3><br/>
<p>Just like <code>NetServer</code>, <code>NetClient</code> also has a set of TCP properties you can set which affect its behaviour. They have the same meaning as those on <code>NetServer</code>.</p>
<p><code>NetClient</code> also has a further set of properties which are used to configure SSL. We'll discuss those later on.</p>
<h2 id="ssl-servers">SSL Servers</h2><br/>
<p>Net servers can also be configured to work with <a href="http://en.wikipedia.org/wiki/Transport_Layer_Security">Transport Layer Security</a> (previously known as SSL).</p>
<p>When a <code>NetServer</code> is working as an SSL Server the API of the <code>NetServer</code> and <code>NetSocket</code> is identical compared to when it working with standard sockets. Getting the server to use SSL is just a matter of configuring the <code>NetServer</code> before <code>listen</code> is called.</p>
<p>To enabled ssl the function <code>setSSL(true)</code> must be called on the Net Server.</p>
<p>The server must also be configured with a <em>key store</em> and an optional <em>trust store</em>.</p>
<p>These are both <em>Java keystores</em> which can be managed using the <a href="http://docs.oracle.com/javase/6/docs/technotes/tools/solaris/keytool.html">keytool</a> utility which ships with the JDK.</p>
<p>The keytool command allows you to create keystores, and import and export certificates from them.</p>
<p>The key store should contain the server certificate. This is mandatory - the client will not be able to connect to the server over ssl if the server does not have a certificate.</p>
<p>The key store is configured on the server using the <code>setKeyStorePath</code> and <code>setKeyStorePassword</code> methods.</p>
<p>The trust store is optional and contains the certificates of any clients it should trust. This is only used if client authentication is required. </p>
<p>To configure a server to use server certificates only:</p>
<pre class="prettyprint">NetServer server = vertx.createNetServer()
.setSSL(true)
.setKeyStorePath("/path/to/your/keystore/server-keystore.jks")
.setKeyStorePassword("password");
</pre>
<p>Making sure that <code>server-keystore.jks</code> contains the server certificate.</p>
<p>To configure a server to also require client certificates:</p>
<pre class="prettyprint">NetServer server = vertx.createNetServer()
.setSSL(true)
.setKeyStorePath("/path/to/your/keystore/server-keystore.jks")
.setKeyStorePassword("password")
.setTrustStorePath("/path/to/your/truststore/server-truststore.jks")