forked from vert-x/vert-x.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dev_guide.html
247 lines (234 loc) · 17.8 KB
/
dev_guide.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
<!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>Developing Vert.x Modules using the Standard Project</h1>
</div>
</div>
</div>
<div class="row">
<div class="span12">
<div class="well">
<div>
<div class="toc">
<ul>
<li><a href="#the-module">The module</a></li>
<li><a href="#the-tests">The tests</a><ul>
<li><a href="#unit-tests">Unit tests</a></li>
<li><a href="#integration-tests">Integration tests</a><ul>
<li><a href="#java-integration-tests">Java integration tests</a></li>
<li><a href="#javascript-integration-tests">JavaScript integration tests</a></li>
<li><a href="#ruby-integration-tests">Ruby integration tests</a></li>
<li><a href="#groovy-integration-tests">Groovy integration tests</a></li>
<li><a href="#python-integration-tests">Python integration tests</a></li>
<li><a href="#run-tests-in-your-ide">Run tests in your IDE</a></li>
<li><a href="#debug-tests-in-your-ide">Debug tests in your IDE</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#run-your-module-and-see-your-changes-immediately">Run your module and see your changes immediately</a><ul>
<li><a href="#working-with-multi-module-applications">Working with Multi Module Applications</a></li>
</ul>
</li>
<li><a href="#other-best-practices">Other best practices</a><ul>
<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>
</ul>
</li>
</ul>
</div>
<p>This document describes <em>best practice</em> for developing Vert.x applications as one or more Vert.x modules using the standard Vert.x project layout. It's highly recommended that you write any non-trivial Vert.x applications as one or more modules.</p>
<p>If your application is relatively small it might make sense to create it as a single module. If your application is large split it up into a set of modules.</p>
<p>It's also recommended you read the Vert.x <a href="manual.html">main manual</a> and the Vert.x <a href="mods_manual.html">modules manual</a> so you understand the basics of Vert.x and modules before starting out.</p>
<p>There should be only one output module per project, so for each module in your application (simple applications may well only have one module) you should create a new project.</p>
<p>The standard layout has a "Maven-style" directory structure that will probably be already familiar with you.</p>
<p>If you're a Gradle user you can clone the <a href="gradle_dev.html">Gradle Template Project</a> to get you started quickly.</p>
<p>If you're a Maven user you'll get the same structure if you use the Vert.x <a href="maven_dev.html">Maven Archetype</a> to create your project (without the Gradle files of course!).</p>
<p>If you prefer to use some other build tool (e.g. ant), that's fine - Vert.x is agnostic about build tool, but you'll have to provide your own build script (perhaps someone could contribute one?) for now.</p>
<p>We'll now explore the standard layout.</p>
<h1 id="the-module">The module</h1><br/>
<p>All Vert.x modules contain a <code>mod.json</code> descriptor. This a file containing some JSON which describes the module. Amongst other things it usually contains a <code>main</code> field.
This tells Vert.x which verticle to run when the module is deployed.</p>
<p>The <code>mod.json</code> file is in the <code>src/main/resources</code> directory of the project. Any files in this directory are copied to the root of the module during packaging.</p>
<p>The thing that is run is called a <code>Verticle</code>. A <code>Verticle</code> can be written in any of the languages that Vert.x supports.</p>
<p>If you've created your project using the Vert.x Maven Archetype or Vert.x Gradle Template you'll see we have a simple Java Verticle called <code>PingVerticle</code>. You can see the source for that in the <code>src/main/java</code> sub tree of the project.</p>
<p>The verticle has a <code>start()</code> method which is called when the verticle is deployed. In the <code>start()</code> method the verticle simply registers a handler on the event bus against address <code>ping-address</code>. The handler will be called when a message is received at that address. When a message is received the verticle simply replies to the <code>ping!</code> with a <code>pong!</code>. </p>
<p>The standard project layout also contains equivalents of the ping verticle written in JavaScript, Groovy (both compiled and script), Ruby and Python. You can edit <code>main</code> in <code>mod.json</code> to tell it to use one of the other versions of the ping verticle.</p>
<h1 id="the-tests">The tests</h1><br/>
<p>The rest of the stuff in the example project is a set of example tests.</p>
<h2 id="unit-tests">Unit tests</h2><br/>
<p>Unit tests are tests that run outside the Vert.x container and which work with your module's Java classes directly. They go by convention in <code>src/test/unit</code>.</p>
<p>You can run unit tests in your IDE as normal by right clicking on the test or on the command line.</p>
<h2 id="integration-tests">Integration tests</h2><br/>
<p>We define <em>integration tests</em> here to mean Vert.x tests that are run <em>inside</em> the Vert.x container.</p>
<p>We provide a custom JUnit test runner which auto-magically takes your tests, starts up a Vert.x container, runs your test in it, and then reports the test results back, all as if the tests had been run locally as normal JUnit tests.</p>
<p>You can even write your tests in JavaScript, Groovy, Ruby or Python and still use the familiar JUnit Assert API.</p>
<p>There are example integration tests for each language in the example project. If you are not interested in writing tests in different languages you can safely delete the files you're not interested in.</p>
<h3 id="java-integration-tests">Java integration tests</h3><br/>
<p>The example Java integration tests are in <code>src/test/java/com/mycompany/integration/java</code></p>
<p>Java integration tests subclass <code>TestVerticle</code> - after all, the test is run inside the Vert.x container as a verticle. Then you just add standard JUnit test methods to it as normal, annotated with <code>@Test</code>.</p>
<p>Please note that the JUnit annotations: <code>@Before</code>, <code>@After</code>, <code>@BeforeClass</code>, <code>@AfterClass</code>, and <code>@Expects</code> are not currently supported.</p>
<p>Vert.x integration tests are asynchronous so they won't necessarily have finished until after the test method completes, therefore to signal that the test has completed you should call the method <code>VertxAssert.testComplete()</code> at the end.</p>
<p>If your test deploys other verticles you can also assert from there and call <code>testComplete</code> from there too.</p>
<p>Please see the example tests for more examples.</p>
<h3 id="javascript-integration-tests">JavaScript integration tests</h3><br/>
<p>The example Java integration tests are in <code>src/test/resources/integration_tests/javascript</code></p>
<p>The class in <code>src/test/java/com/mycompany/integration/javascript</code> is just a stub class that tells JUnit where the real JavaScript tests are. You can safely ignore it.</p>
<h3 id="ruby-integration-tests">Ruby integration tests</h3><br/>
<p>The example Java integration tests are in <code>src/test/resources/integration_tests/ruby</code></p>
<p>The class in <code>src/test/java/com/mycompany/integration/ruby</code> is just a stub class that tells JUnit where the real Ruby tests are. You can safely ignore it.</p>
<h3 id="groovy-integration-tests">Groovy integration tests</h3><br/>
<p>The example Java integration tests are in <code>src/test/resources/integration_tests/groovy</code></p>
<p>The class in <code>src/test/java/com/mycompany/integration/groovy</code> is just a stub class that tells JUnit where the real Groovy tests are. You can safely ignore it.</p>
<h3 id="python-integration-tests">Python integration tests</h3><br/>
<p>The example Java integration tests are in <code>src/test/resources/integration_tests/python</code></p>
<p>The class in <code>src/test/java/com/mycompany/integration/python</code> is just a stub class that tells JUnit where the real Python tests are. You can safely ignore it.</p>
<h3 id="run-tests-in-your-ide">Run tests in your IDE</h3><br/>
<p>To run Vert.x integration tests in your IDE, simply open the folder <code>src/test/java/com/mycompany/integration</code> in your IDE and right click it and chose to run all tests as JUnit tests (how this is done depends on your IDE). Or you can select individual test classes.</p>
<p>You'll need to make sure you don't have a module built using the command line when running tests in the IDE. Execute <code>./gradlew clean</code> or <code>mvn clean</code> to make sure or the test run will pick up resources from there instead.</p>
<p><em>Note that you can change your code or config and re-run the tests and Vert.x will pick up the changes without you having to rebuild at the command line!</em></p>
<p>You can also run the tests at the command line if you prefer (using <code>mvn integration-tests</code> or <code>./gradlew test</code>)</p>
<h3 id="debug-tests-in-your-ide">Debug tests in your IDE</h3><br/>
<p>You can also set breakpoints in your Java code for seamless debugging into your Vert.x verticles and modules as normal. No special set-up is required</p>
<p><a id="auto-redeploy"> </a></p>
<h1 id="run-your-module-and-see-your-changes-immediately">Run your module and see your changes immediately</h1><br/>
<p>When developing a Vert.x module, especially if it has a web interface, it's often useful to have your module running and have it automatically pick up any changes in classes or other resources in the module <em>without you having to rebuild the module</em>.</p>
<p>To get this to work your module must be marked as:</p>
<pre class="prettyprint">"auto-redeploy": true
</pre>
<p>In your <code>mod.json</code>. See the <a href="mods_manual.html#auto-redeploy">modules manual</a> for more information on this.</p>
<p>If you haven't done so already, you can create project files for your IDE using:</p>
<pre class="prettyprint">./gradlew idea
</pre>
<p>Or</p>
<pre class="prettyprint">./gradlew eclipse
</pre>
<p>Now open your project file in your IDE, and set your project in your IDE to automatically compile when source files are saved - how to do this depends on your particular IDE so consult your IDE documentation if in doubt.</p>
<p>Now, make sure your IDE has built your project at least once (e.g. hit CTRL-F9 in IntelliJ IDEA).</p>
<p><em>Note you should make sure there is no previously built module lurking in the <code>target/mods</code> directory - of one is found there then <code>runMod</code> will deploy that, not the module corresponding to the resources in your IDE. So delete target/mods if it exists before running <code>runMod</code>.</em></p>
<p>Then, if you're using the standard Vert.x Gradle Template project, you can run the following from a console in your project directory:</p>
<pre class="prettyprint">./gradlew runMod -i
</pre>
<p>This will start Vert.x running and it will monitor the file system to changes to your module as you edit them and save your changes.</p>
<p>If you want to provide command line arguments to the running module, e.g. you want to specify a config file you can edit the <code>runModArgs</code> property in `gradle.properties".</p>
<p>Note that we use the -i switch when running <code>gradlew</code> - this tells Gradle not to swallow INFO level debug output when running. By default Gradle swallows all logging output (!)</p>
<p>If you're using Maven you can run the following from a console in your project directory:</p>
<pre class="prettyprint">mvn clean vertx:runMod
</pre>
<p>This will start Vert.x running and it will monitor the file system to changes to your module as you edit them and save your changes.</p>
<p>By installing the Maven or Gradle plugin for your IDE you should be able to run the runMod tasks directly in the IDE.</p>
<p>Vert.x uses the file <code>vertx_classpath.txt</code> to determine where to find the resources of your module during development. This file is configured for standard directories used by both IntelliJ IDEA and Eclipse, but if you have put your resources in a different place you can edit this file to point at where the resources are.</p>
<p>If you don't use Maven or Gradle but still want to see your changes in a running module immediately you can run the following from a console in your project directory:</p>
<pre class="prettyprint">vertx create-module-link com.yourcompany~your-module~1.0
vertx runmod com.yourcompany~your-module~1.0
</pre>
<h2 id="working-with-multi-module-applications">Working with Multi Module Applications</h2><br/>
<p>For larger applications it makes sense to implement them as a set of Vert.x modules.</p>
<p>The application should be made up of several projects (probably created using the Maven archetype or Gradle template), each outputting a single module.</p>
<p>You can then use</p>
<pre class="prettyprint">mvn install
</pre>
<p>Or</p>
<pre class="prettyprint">./gradlew install
</pre>
<p>From any of the projects to install that module in your local Maven repository, and it will be automatically picked up by your other modules which use it. Vert.x module system understands how to pull modules from local (as well as remote) Maven repositories.</p>
<p>If you want to enable auto-redeploy for all modules in a multi-module project then it's recommended that you set <code>VERTX_MODS</code> to point to a directory in the parent directory for your modules.</p>
<p>Then in each module project directory execute:</p>
<pre class="prettyprint">vertx create-link <module_name>
</pre>
<p>This only has to be done once.</p>
<p>Then just run the main module with <code>vertx runmod</code> as normal and any changes in sub modules will be picked up causing redeployment.</p>
<h1 id="other-best-practices">Other best practices</h1><br/>
<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 application 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>app.js</code> (you could use another scripting language - Ruby, Groovy or Python if you prefer) as follows:</p>
<pre class="prettyprint">// Start the verticles that make up the app
vertx.deployVerticle("verticle1.js", appConfig.verticle1Config);
vertx.deployVerticle("verticle2.js", appConfig.verticle2Config, 5);
vertx.deployVerticle("verticle3.js", appConfig.verticle3Config);
vertx.deployWorkerVerticle("verticle4.js", appConfig.verticle4Config);
vertx.deployWorkerVerticle("verticle5.js", appConfig.verticle5Config, 10);
</pre>
<p>Then set the <code>app.js</code> verticle 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 conf.json
</pre>
<p>Where conf.json is a config file like:</p>
<pre class="prettyprint">// Application config
{
verticle1Config: {
// Config for verticle1
},
verticle2Config: {
// Config for verticle2
},
verticle3Config: {
// Config for verticle3
},
verticle4Config: {
// Config for verticle4
},
verticle5Config: {
// Config for verticle5
}
}
</pre>
<p>If your application is large and actually composed of multiple modules rather than verticles you can use the same technique.</p></div>
</div>
</div>
</div>
</div>
</body>
</html>