source: release-kits/lirk3/bin/ant-installer/web/manual1.7.0/manual/tutorial-HelloWorldWithAnt.html@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 18.7 KB
Line 
1<!--
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16-->
17<html>
18<head>
19 <title>Tutorial: Hello World with Ant</title>
20 <meta name="author" content="Jan Matï¿œne">
21 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
22 <style type="text/css">
23 <!--
24 .code { background: #EFEFEF; margin-top: }
25 .output { color: #FFFFFF; background: #837A67; }
26 -->
27 </style>
28</head>
29<body>
30<h1>Tutorial: Hello World with Ant</h1>
31
32<p>This document provides a step by step tutorial for starting java programming with Ant.
33It does <b>not</b> contain deeper knowledge about Java or Ant. This tutorial has the goal
34to let you see, how to do the easiest steps in Ant.</p>
35
36
37
38<h2>Content</h2>
39<p><ul>
40<li><a href="#prepare">Preparing the project</a></li>
41<li><a href="#four-steps">Enhance the build file</a></li>
42<li><a href="#enhance">Enhance the build file</a></li>
43<li><a href="#ext-libs">Using external libraries</a></li>
44<li><a href="#resources">Resources</a></li>
45</ul></p>
46
47
48<a name="prepare"></a>
49<h2>Preparing the project</h2>
50<p>We want to separate the source from the generated files, so our java source files will
51be in <tt>src</tt> folder. All generated files should be under <tt>build</tt>, and there
52splitted into several subdirectories for the individual steps: <tt>classes</tt> for our compiled
53files and <tt>jar</tt> for our own JAR-file.</p>
54<p>We have to create only the <tt>src</tt> directory. (Because I am working on Windows, here is
55the win-syntax - translate to your shell):</p>
56
57<pre class="code">
58md src
59</pre>
60
61<p>The following simple Java class just prints a fixed message out to STDOUT,
62so just write this code into <tt>src\oata\HelloWorld.java</tt>.</p>
63
64<pre class="code">
65package oata;
66
67public class HelloWorld {
68 public static void main(String[] args) {
69 System.out.println("Hello World");
70 }
71}
72</pre>
73
74<p>Now just try to compile and run that:
75<pre class="code">
76md build\classes
77javac -sourcepath src -d build\classes src\oata\HelloWorld.java
78java -cp build\classes oata.HelloWorld
79</pre>
80which will result in
81<pre class="output">
82Hello World
83</pre>
84</p>
85
86<p>Creating a jar-file is not very difficult. But creating a <i>startable</i> jar-file needs more steps: create a
87manifest-file containing the start class, creating the target directory and archiving the files.</p>
88<pre class="code">
89echo Main-Class: oata.HelloWorld&gt;myManifest
90md build\jar
91jar cfm build\jar\HelloWorld.jar myManifest -C build\classes .
92java -jar build\jar\HelloWorld.jar
93</pre>
94
95<p><b>Note:</b> Do not have blanks around the &gt;-sign in the <tt>echo Main-Class</tt> instruction because it would
96falsify it!</p>
97
98
99<a name="four-steps"></a>
100<h2>Four steps to a running application</h2>
101<p>After finishing the java-only step we have to think about our build process. We <i>have</i> to compile our code, otherwise we couldn't
102start the program. Oh - "start" - yes, we could provide a target for that. We <i>should</i> package our application.
103Now it's only one class - but if you want to provide a download, no one would download several hundreds files ...
104(think about a complex Swing GUI - so let us create a jar file. A startable jar file would be nice ... And it's a
105good practise to have a "clean" target, which deletes all the generated stuff. Many failures could be solved just
106by a "clean build".</p>
107
108<p>By default Ant uses <tt>build.xml</tt> as the name for a buildfile, so our <tt>.\build.xml</tt> would be:</p>
109<pre class="code">
110&lt;project&gt;
111
112 &lt;target name="clean"&gt;
113 &lt;delete dir="build"/&gt;
114 &lt;/target&gt;
115
116 &lt;target name="compile"&gt;
117 &lt;mkdir dir="build/classes"/&gt;
118 &lt;javac srcdir="src" destdir="build/classes"/&gt;
119 &lt;/target&gt;
120
121 &lt;target name="jar"&gt;
122 &lt;mkdir dir="build/jar"/&gt;
123 &lt;jar destfile="build/jar/HelloWorld.jar" basedir="build/classes"&gt;
124 &lt;manifest&gt;
125 &lt;attribute name="Main-Class" value="oata.HelloWorld"/&gt;
126 &lt;/manifest&gt;
127 &lt;/jar&gt;
128 &lt;/target&gt;
129
130 &lt;target name="run"&gt;
131 &lt;java jar="build/jar/HelloWorld.jar" fork="true"/&gt;
132 &lt;/target&gt;
133
134&lt;/project&gt;
135</pre>
136
137<p>Now you can compile, package and run the application via</p>
138<pre class="code">
139ant compile
140ant jar
141ant run
142</pre>
143<p>Or shorter with</p>
144<pre class="code">
145ant compile jar run
146</pre>
147
148<p>While having a look at the buildfile, we will see some similar steps between Ant and the java-only commands:
149<table>
150<tr>
151 <th>java-only</th>
152 <th>Ant</th>
153</tr>
154<tr>
155 <td valign="top"><pre class="code">
156md build\classes
157javac
158 -sourcepath src
159 -d build\classes
160 src\oata\HelloWorld.java
161echo Main-Class: oata.HelloWorld>mf
162md build\jar
163jar cfm
164 build\jar\HelloWorld.jar
165 mf
166 -C build\classes
167 .
168
169
170
171java -jar build\jar\HelloWorld.jar
172 </pre></td>
173 <td valign="top"><pre class="code">
174&lt;mkdir dir="build/classes"/&gt;
175&lt;javac
176 srcdir="src"
177 destdir="build/classes"/&gt;
178<i>&lt;!-- automatically detected --&gt;</i>
179<i>&lt;!-- obsolete; done via manifest tag --&gt;</i>
180&lt;mkdir dir="build/jar"/&gt;
181&lt;jar
182 destfile="build/jar/HelloWorld.jar"
183
184 basedir="build/classes"&gt;
185 &lt;manifest&gt;
186 &lt;attribute name="Main-Class" value="oata.HelloWorld"/&gt;
187 &lt;/manifest&gt;
188&lt;/jar&gt;
189&lt;java jar="build/jar/HelloWorld.jar" fork="true"/&gt;
190 </pre></td>
191</tr></table>
192</p>
193
194
195
196<a name="enhance"></a>
197<h2>Enhance the build file</h2>
198<p>Now we have a working buildfile we could do some enhancements: many time you are referencing the
199same directories, main-class and jar-name are hard coded, and while invocation you have to remember
200the right order of build steps.</p>
201<p>The first and second point would be addressed with <i>properties</i>, the third with a special property - an attribute
202of the &lt;project&gt;-tag and the fourth problem can be solved using dependencies.</p>
203
204
205<pre class="code">
206&lt;project name="HelloWorld" basedir="." default="main"&gt;
207
208 &lt;property name="src.dir" value="src"/&gt;
209
210 &lt;property name="build.dir" value="build"/&gt;
211 &lt;property name="classes.dir" value="${build.dir}/classes"/&gt;
212 &lt;property name="jar.dir" value="${build.dir}/jar"/&gt;
213
214 &lt;property name="main-class" value="oata.HelloWorld"/&gt;
215
216
217
218 &lt;target name="clean"&gt;
219 &lt;delete dir="${build.dir}"/&gt;
220 &lt;/target&gt;
221
222 &lt;target name="compile"&gt;
223 &lt;mkdir dir="${classes.dir}"/&gt;
224 &lt;javac srcdir="${src.dir}" destdir="${classes.dir}"/&gt;
225 &lt;/target&gt;
226
227 &lt;target name="jar" depends="compile"&gt;
228 &lt;mkdir dir="${jar.dir}"/&gt;
229 &lt;jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}"&gt;
230 &lt;manifest&gt;
231 &lt;attribute name="Main-Class" value="${main-class}"/&gt;
232 &lt;/manifest&gt;
233 &lt;/jar&gt;
234 &lt;/target&gt;
235
236 &lt;target name="run" depends="jar"&gt;
237 &lt;java jar="${jar.dir}/${ant.project.name}.jar" fork="true"/&gt;
238 &lt;/target&gt;
239
240 &lt;target name="clean-build" depends="clean,jar"/&gt;
241
242 &lt;target name="main" depends="clean,run"/&gt;
243
244&lt;/project&gt;
245</pre>
246
247
248<p>Now it's easier, just do a <tt class="code">ant</tt> and you will get</p>
249<pre class="output">
250Buildfile: build.xml
251
252clean:
253
254compile:
255 [mkdir] Created dir: C:\...\build\classes
256 [javac] Compiling 1 source file to C:\...\build\classes
257
258jar:
259 [mkdir] Created dir: C:\...\build\jar
260 [jar] Building jar: C:\...\build\jar\HelloWorld.jar
261
262run:
263 [java] Hello World
264
265main:
266
267BUILD SUCCESSFUL
268</pre>
269
270
271<a name="ext-libs"></a>
272<h2>Using external libraries</h2>
273<p>Somehow told us not to use syso-statements. For log-Statements we should use a Logging-API - customizable on a high
274degree (including switching off during usual life (= not development) execution). We use Log4J for that, because <ul>
275<li>it is not part of the JDK (1.4+) and we want to show how to use external libs</li>
276<li>it can run under JDK 1.2 (as Ant)</li>
277<li>it's highly configurable</li>
278<li>it's from Apache ;-)</li>
279</ul></p>
280<p>We store our external libraries in a new directory <tt>lib</tt>. Log4J can be
281<a href="http://www.apache.org/dist/logging/log4j/1.2.13/logging-log4j-1.2.13.zip">downloaded [1]</a> from Logging's Homepage.
282Create the <tt>lib</tt> directory and extract the log4j-1.2.9.jar into that lib-directory. After that we have to modify
283our java source to use that library and our buildfile so that this library could be accessed during compilation and run.
284</p>
285<p>Working with Log4J is documented inside its manual. Here we use the <i>MyApp</i>-example from the
286<a href="http://logging.apache.org/log4j/docs/manual.html">Short Manual [2]</a>. First we have to modify the java source to
287use the logging framework:</p>
288
289<pre class="code">
290package oata;
291
292<b>import org.apache.log4j.Logger;</b>
293<b>import org.apache.log4j.BasicConfigurator;</b>
294
295public class HelloWorld {
296 <b>static Logger logger = Logger.getLogger(HelloWorld.class);</b>
297
298 public static void main(String[] args) {
299 <b>BasicConfigurator.configure();</b>
300 <font color="blue"><b>logger.info("Hello World");</b></font> // the old SysO-statement
301 }
302}
303</pre>
304
305<p>Most of the modifications are "framework overhead" which has to be done once. The blue line is our "old System-out"
306statement.</p>
307<p>Don't try to run <tt>ant</tt> - you will only get lot of compiler errors. Log4J is not inside the classpath so we have
308to do a little work here. But do not change the CLASSPATH environment variable! This is only for this project and maybe
309you would break other environments (this is one of the most famous mistakes when working with Ant). We introduce Log4J
310(or to be more precise: all libraries (jar-files) which are somewhere under <tt>.\lib</tt>) into our buildfile:</p>
311
312<pre class="code">
313&lt;project name="HelloWorld" basedir="." default="main"&gt;
314 ...
315 <b>&lt;property name="lib.dir" value="lib"/&gt;</b>
316
317 <b>&lt;path id="classpath"&gt;</b>
318 <b>&lt;fileset dir="${lib.dir}" includes="**/*.jar"/&gt;</b>
319 <b>&lt;/path&gt;</b>
320
321 ...
322
323 &lt;target name="compile"&gt;
324 &lt;mkdir dir="${classes.dir}"/&gt;
325 &lt;javac srcdir="${src.dir}" destdir="${classes.dir}" <b>classpathref="classpath"</b>/&gt;
326 &lt;/target&gt;
327
328 &lt;target name="run" depends="jar"&gt;
329 &lt;java fork="true" <b>classname="${main-class}"</b>&gt;
330 <b>&lt;classpath&gt;</b>
331 <b>&lt;path refid="classpath"/&gt;</b>
332 <font color="red"><b>&lt;path location="${jar.dir}/${ant.project.name}.jar"/&gt;</b></font>
333 <b>&lt;/classpath&gt;</b>
334 &lt;/java&gt;
335 &lt;/target&gt;
336
337 ...
338
339&lt;/project&gt;
340</pre>
341
342<p>In this example we start our application not via its Main-Class manifest-attribute, because we could not provide
343a jarname <i>and</i> a classpath. So add our class in the red line to the already defined path and start as usual. Running
344<tt>ant</tt> would give (after the usual compile stuff):</p>
345
346<pre class="output">
347[java] 0 [main] INFO oata.HelloWorld - Hello World
348</pre>
349
350<p>What's that? <ul>
351<li><i>[java]</i> Ant task running at the moment</li>
352<li><i>0</i> <font size="-1">sorry don't know - some Log4J stuff</font></li>
353<li><i>[main]</i> the running thread from our application </li>
354<li><i>INFO</i> log level of that statement</i>
355<li><i>oata.HelloWorld</i> source of that statement</i>
356<li><i>-</i> separator</li>
357<li><i>Hello World</i> the message</li>
358</ul>
359For another layout ... have a look inside Log4J's documentation about using other PatternLayout's.</p>
360
361
362<a name="config-files"></a>
363<h2>Configuration files</h2>
364<p>Why we have used Log4J? "It's highly configurable"? No - all is hard coded! But that is not the debt of Log4J - it's
365ours. We had coded <tt>BasicConfigurator.configure();</tt> which implies a simple, but hard coded configuration. More
366confortable would be using a property file. In the java source delete the BasicConfiguration-line from the main() method
367(and the related import-statement). Log4J will search then for a configuration as described in it's manual. Then create
368a new file <tt>src/log4j.properties</tt>. That's the default name for Log4J's configuration and using that name would make
369life easier - not only the framework knows what is inside, you too!</p>
370
371<pre class="code">
372log4j.rootLogger=DEBUG, <b>stdout</b>
373
374log4j.appender.<b>stdout</b>=org.apache.log4j.ConsoleAppender
375
376log4j.appender.<b>stdout</b>.layout=org.apache.log4j.PatternLayout
377log4j.appender.<b>stdout</b>.layout.ConversionPattern=<font color="blue"><b>%m%n</b></font>
378</pre>
379
380<p>This configuration creates an output channel ("Appender") to console named as <tt>stdout</tt> which prints the
381message (%m) followed by a line feed (%n) - same as the earlier System.out.println() :-) Oooh kay - but we haven't
382finished yet. We should deliver the configuration file, too. So we change the buildfile:</p>
383
384<pre class="code">
385 ...
386 &lt;target name="compile"&gt;
387 &lt;mkdir dir="${classes.dir}"/&gt;
388 &lt;javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/&gt;
389 <b>&lt;copy todir="${classes.dir}"&gt;</b>
390 <b>&lt;fileset dir="${src.dir}" excludes="**/*.java"/&gt;</b>
391 <b>&lt;/copy&gt;</b>
392 &lt;/target&gt;
393 ...
394</pre>
395
396<p>This copies all resources (as long as they haven't the suffix ".java") to the build directory, so we could
397start the application from that directory and these files will included into the jar.</p>
398
399
400<a name="junit"></a>
401<h2>Testing the class</h2>
402<p>In this step we will introduce the usage of the JUnit [3] testframework in combination with Ant. Because Ant
403has a built-in JUnit 3.8.2 you could start directly using it. Write a test class in <tt>src\HelloWorldTest.java</tt>: </p>
404
405<pre class="code">
406public class HelloWorldTest extends junit.framework.TestCase {
407
408 public void testNothing() {
409 }
410
411 public void testWillAlwaysFail() {
412 fail("An error message");
413 }
414
415}</pre>
416
417<p>Because we dont have real business logic to test, this test class is very small: just show how to start. For
418further information see the JUnit documentation [3] and the manual of <a href="OptionalTasks/junit.html">junit</a> task.
419Now we add a junit instruction to our buildfile:</p>
420
421<pre class="code">
422 ...
423
424 &lt;target name="run" depends="jar"&gt;
425 &lt;java fork="true" classname="${main-class}"&gt;
426 &lt;classpath&gt;
427 &lt;path refid="classpath"/&gt;
428 &lt;path <b>id="application"</b> location="${jar.dir}/${ant.project.name}.jar"/&gt;
429 &lt;/classpath&gt;
430 &lt;/java&gt;
431 &lt;/target&gt;
432
433 <b>&lt;target name="junit" depends="jar"&gt;
434 &lt;junit printsummary="yes"&gt;
435 &lt;classpath&gt;
436 &lt;path refid="classpath"/&gt;
437 &lt;path refid="application"/&gt;
438 &lt;/classpath&gt;
439
440 &lt;batchtest fork="yes"&gt;
441 &lt;fileset dir="${src.dir}" includes="*Test.java"/&gt;
442 &lt;/batchtest&gt;
443 &lt;/junit&gt;
444 &lt;/target&gt;</b>
445
446 ...
447
448</pre>
449
450<p>We reuse the path to our own jar file as defined in run-target by giving it an ID.
451The <tt>printsummary=yes</tt> lets us see more detailed information than just a "FAILED" or "PASSED" message.
452How much tests failed? Some errors? Printsummary lets us know. The classpath is set up to find our classes.
453To run tests the <tt>batchtest</tt> here is used, so you could easily add more test classes in the future just
454by naming them <tt>*Test.java</tt>. This is a common naming scheme.</p>
455
456<p>After a <tt class="code">ant junit</tt> you'll get:</p>
457
458<pre class="output">
459...
460junit:
461 [junit] Running HelloWorldTest
462 [junit] Tests run: 2, Failures: 1, Errors: 0, Time elapsed: 0,01 sec
463 [junit] Test HelloWorldTest FAILED
464
465BUILD SUCCESSFUL
466...
467</pre>
468
469<p>We can also produce a report. Something that you (and other) could read after closing the shell ....
470There are two steps: 1. let &lt;junit&gt; log the information and 2. convert these to something readable (browsable).<p>
471
472<pre class="code">
473 ...
474 <b>&lt;property name="report.dir" value="${build.dir}/junitreport"/&gt;</b>
475 ...
476 &lt;target name="junit" depends="jar"&gt;
477 <b>&lt;mkdir dir="${report.dir}"/&gt;</b>
478 &lt;junit printsummary="yes"&gt;
479 &lt;classpath&gt;
480 &lt;path refid="classpath"/&gt;
481 &lt;path refid="application"/&gt;
482 &lt;/classpath&gt;
483
484 <b>&lt;formatter type="xml"/&gt;</b>
485
486 &lt;batchtest fork="yes" <b>todir="${report.dir}"</b>&gt;
487 &lt;fileset dir="${src.dir}" includes="*Test.java"/&gt;
488 &lt;/batchtest&gt;
489 &lt;/junit&gt;
490 &lt;/target&gt;
491
492 <b>&lt;target name="junitreport"&gt;
493 &lt;junitreport todir="${report.dir}"&gt;
494 &lt;fileset dir="${report.dir}" includes="TEST-*.xml"/&gt;
495 &lt;report todir="${report.dir}"/&gt;
496 &lt;/junitreport&gt;
497 &lt;/target&gt;</b>
498
499</pre>
500
501<p>Because we would produce a lot of files and these files would be written to the current directory by default,
502we define a report directory, create it before running the <tt>junit</tt> and redirect the logging to it. The log format
503is XML so <tt>junitreport</tt> could parse it. In a second target <tt>junitreport</tt> should create a browsable
504HTML-report for all generated xml-log files in the report directory. Now you can open the ${report.dir}\index.html and
505see the result (looks something like JavaDoc).<br>
506Personally I use two different targets for junit and junitreport. Generating the HTML report needs some time and you dont
507need the HTML report just for testing, e.g. if you are fixing an error or a integration server is doing a job.
508</p>
509
510
511
512
513<a name="resources"></a>
514<h2>Resources</h2>
515<pre>
516 [1] <a href="http://www.apache.org/dist/logging/log4j/1.2.13/logging-log4j-1.2.13.zip">http://www.apache.org/dist/logging/log4j/1.2.13/logging-log4j-1.2.13.zip</a>
517 [2] <a href="http://logging.apache.org/log4j/docs/manual.html">http://logging.apache.org/log4j/docs/manual.html</a>
518 [3] <a href="http://www.junit.org/index.htm">http://www.junit.org/index.htm</a>
519</pre>
520
521
522
523
524</body>
525</html>
Note: See TracBrowser for help on using the repository browser.