You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

tutorial-HelloWorldWithAnt.html 18 KiB

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