Java Development with Ant
Java Development with Ant
ERIK HATCHER STEVE LOUGHRAN
MANNING
Greenwich (74° w. long.)
For online information and ordering of this and other Manning books, go to www.manning.com. The publisher offers discounts on this book when ordered in quantity. For more information, please contact: Special Sales Department Manning Publications Co. 209 Bruce Park Avenue Greenwich, CT 06830
Fax: (203) 661-9018 email: orders@manning.com
©2003 by Manning Publications Co. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in the book, and Manning Publications was aware of a trademark claim, the designations have been printed in initial caps or all caps. Recognizing the importance of preserving what has been written, it is Manning’s policy to have the books we publish printed on acid-free paper, and we exert our best efforts to that end.
Manning Publications Co. 209 Bruce Park Avenue Greenwich, CT 06830
Copyeditor: Maarten Reilingh Typesetter: Martine Maguire-Weltecke Cover designer: Leslie Haimes
ISBN 1930110588 Printed in the United States of America 1 2 3 4 5 6 7 8 9 10 – VHG – 06 05 04 03 02
To my wife Carole and our two sons, Jakob and Ethan. Thank you for taking care of me while I took care of this book. Erik
To Bina and Alexander. Thank you for being so patient during the long hours of this project. Steve
brief contents
Part 1 Learning Ant 1
1 Introducing Ant 3 23 47
2 Getting started with Ant
3 Understanding Ant datatypes and properties 4 Testing with JUnit 5 Executing programs 6 Packaging projects 7 Deployment 163 188 85 111 134
8 Putting it all together
Part 2
Applying Ant 203
9 Using Ant in your development projects 10 Beyond Ant’s core tasks 11 XDoclet 260 234 205
vii
12 Developing for the web 13 Working with XML 14 Enterprise JavaBeans
278
317 333 355
15 Working with web services 16 Continuous integration 17 Developing native code 18 Production deployment
386 407 431
Part 3
Extending Ant 465
19 Writing Ant tasks 467 498
20 Extending Ant further
Appendices
A Installation 523 532
B XML primer as it applies to Ant C IDE integration 536 544
D The elements of Ant style E Ant task reference 561
viii
BRIEF CONTENTS
contents
foreword xxv preface xxvii acknowledgments xxix about this book xxxi about the authors xxxvi about the cover illustration
xxxvii
Part 1
Learning Ant 1
1 Introducing Ant 3
1.1 What is Ant? 3
What is a build process and why do you need one? 4 Why do we think Ant makes a great build tool? 4
1.2 The core concepts of Ant
An example project 7
5
1.3 Why use Ant? 10
Integrated development environments Make 11 ✦ Other build tools 13 Up and running, in no time 14 10
1.4 The evolution of Ant 14 1.5 Ant and software development methodologies 16
eXtreme Programming 16 Rational Unified Process 17
1.6 Our example project
17
18
Documentation search engine—example Ant project
1.7 Yeah, but can Ant… 19 1.8 Beyond Java development
21
21
Web publishing engine 21 ✦ Simple workflow engine Microsoft .NET and other languages 21
1.9 Summary
22
ix
2 Getting started with Ant
23
2.1 Defining our first project 23 2.2 Step one: verifying the tools are in place 24 2.3 Step two: writing your first Ant build file 24
Examining the build file If the build fails 25 29
2.4 Step three: running your first build 26
27 ✦ Looking at the build in more detail
2.5 Step four: imposing structure 31
Laying out the source directories 32 ✦ Laying out the build directories 33 ✦ Laying out the dist directories 34 Creating the build file 35 ✦ Target dependencies 35 Running the new build file 36 ✦ Rerunning the build 37 How Ant handles multiple targets on the command line 38
2.6 Step five: running our program
39
40
Why execute from inside Ant 39 Adding an execute target 40 ✦ Running the new target
2.7 Ant command line options
41
42
Specifying which build file to run 42 Controlling the amount of information provided Getting information about a project 44
2.8 The final build file 44 2.9 Summary 46
3 Understanding Ant datatypes and properties
3.1 Preliminaries 48
48 ✦ Property overview 48 Datatype overview
47
3.2 Introducing datatypes and properties with
49 3.3 Paths 51 3.4 Filesets 52
Fileset examples 53 ✦ Default excludes 53
3.5 3.6 3.7 3.8
Patternsets 54 Selectors 56 Datatype element naming 57 Filterset 58
Inserting date stamps in files at build-time 58
3.9 FilterChains and FilterReaders 3.10 Mappers 61
59
Identity mapper 61 ✦ Flatten mapper 62 Merge mapper 62 ✦ Glob mapper 63 Regexp mapper 63 ✦ Package mapper 64
x
CONTENTS
3.11 Additional Ant datatypes
65
ZipFileset 65 ✦ Dirset 65 Filelist 65 ✦ ClassFileset 66
3.12 Properties
66
Setting properties with the task 67 How the task is different 70 Checking for the availability of resources: 70 Saving time by skipping unnecessary steps: 72 Testing conditions with 72 Setting properties from the command-line 74 Creating a build timestamp with 75 Loading properties from an XML file 76
3.13 Controlling Ant with properties 77
Conditional target execution 77 Conditional patternset inclusion/exclusion Conditional build failure 78 78
3.14 References 79
Properties and references 80 Using references for nested patternsets 81
3.15 Best practices 82 3.16 Summary 83
4 Testing with JUnit
85
4.1 Refactoring 86 4.2 Java main() testing 86 4.3 JUnit primer 87
Writing a test case 88 ✦ Running a test case 88 Asserting desired results 88 ✦ TestCase lifecycle 90 Writing a TestSuite 90 ✦ Obtaining and installing JUnit Extensions to JUnit 91 91
4.4 Applying unit tests to our application
92
93 94
Writing the test first 92 Dealing with external resources during testing
4.5 The JUnit task— 94
Structure directories to accommodate testing Fitting JUnit into the build process 95
4.6 Test failures are build failures 97
Capturing test results 97 ✦ Running multiple tests Creating your own results formatter 100 99
4.7 Generating test result reports
100
Generate reports and allow test failures to fail the build 102 Run a single test case from the command-line 103 Initializing the test environment 103 ✦ Other test issues 104
CONTEN TS
xi
4.8 Short-circuiting tests 105
Dealing with large number of tests 108
4.9 Best practices 109 4.10 Summary 110
5 Executing programs
111
111
5.1 Why you need to run external programs 5.2 Running Java programs 112
Introducing the task 113 ✦ Setting the classpath 114 Arguments 115 ✦ Defining system properties 116 Running the program in a new JVM 117 Setting environment variables 118 ✦ Controlling the new JVM 118 ✦ Handling errors with failonerror 119 Executing JAR files 120 ✦ Calling third-party programs 121 Probing for a Java program before calling it 123 Setting a timeout 124
5.3 Starting native programs with
124
129
Setting environment variables 126 ✦ Handling errors 126 Handling timeouts 127 ✦ Making and executing shell commands 127 ✦ Probing for a program before calling it
5.4 5.5 5.6 5.7 5.8
Bulk execution with 130 Processing output 131 Limitations on execution 132 Best practices 132 Summary 133
6 Packaging projects
134
136
6.1 Moving, copying, and deleting files 135
How to delete files 135 ✦ How to copy files How to move files 137 ✦ Filtering 138
6.2 Preparing to package
139
142
Building and documenting release code 139 Adding data files 141 ✦ Preparing documentation Preparing install scripts and documents 143 Preparing libraries for redistribution 145
6.3 Creating archive files 146
JAR files 148 ✦ Creating a JAR file 148 Testing the JAR file 149 ✦ Creating JAR manifests 150 Adding extra metadata to the JAR 152 JAR file best practices 152 ✦ Signing JAR files 152
xii
CONTENTS
6.4 Creating Zip files 154
Creating a binary distribution 154 ✦ Creating a source distribution 156 ✦ Merging Zip files 157 Zip file best practices 157
6.5 6.6 6.7 6.8
Creating tar files 158 Creating web applications with WAR files 160 Testing packaging 161 Summary 162
7 Deployment
163
164 ✦ Tools for deployment 164
7.1 Example deployment problems 164
Reviewing the tasks
7.2 Tasks for deployment 165
File transfer with 166 ✦ Probing for server availability 166 Inserting pauses into the build with 168 Ant’s email task 169 ✦ Fetching remote files with 170 Using the tasks to deploy 171
7.3 FTP-based distribution of a packaged application
Asking for information with the task 172
171 173
7.4 Email-based distribution of a packaged application 7.5 Local deployment to Tomcat 4.x 174
The Tomcat management servlet API 175 Deploying to Tomcat with Ant 176
7.6 Remote deployment to Tomcat
181
182
Interlude: calling targets with Using in deployment 185
7.7 Testing deployment 7.8 Summary 187
187
8 Putting it all together
8.1 8.2 8.3 8.4
188
Our application thus far 188 Building the custom Ant task library 189 Loading common properties across multiple projects Handling versioned dependencies 196
Installing a new library version 198
194
8.5 Build file philosophy 200
Begin with the end in mind 200 ✦ Integrate tests with the build 200 ✦ Support automated deployment 200 Make it portable 200 ✦ Allow for customizations 201
8.6 Summary
CONTEN TS
201
xiii
Part 2
Applying Ant 203
9 Using Ant in your development projects 205
208
9.1 Designing an Ant-based build process 206
Analyzing your project 206 ✦ Creating the core build file Evolve the build file 208
9.2 Migrating to Ant 209 9.3 The ten steps of migration
210
Migrating from Make-based projects 211 Migrating from IDE-based projects 211
9.4 Master builds: managing large projects
212
213
Refactoring build files 212 ✦ Introducing the task Example: a basic master build file 213 Designing a scalable, flexible master build file 215
9.5 Managing child project builds 221
How to control properties of child projects 221 Inheriting properties and references from a master build file Declaring properties and references in 224 Sharing properties via XML file fragments 225 Sharing targets with XML file fragments 227 223
9.6 Creating reusable library build files 228 9.7 Looking ahead: large project support evolution 9.8 Ant project best practices 231
Managing libraries
230
232
232 ✦ Implementing processes
9.9 Summary
233
10 Beyond Ant’s core tasks
234
10.1 Understanding types of tasks 235
So, what is an “optional” task? 235 ✦ Ant’s major optional tasks 236 ✦ Why third-party tasks? 237
10.2 Optional tasks in action
237
Manipulating property files 237 Adding audio and visual feedback during a build 239 Adding dependency checks 241 ✦ Grammar parsing with JavaCC 243 ✦ Regular expression replacement 244
10.3 Using software configuration management tasks
CVS 245 ✦ ClearCase 246
245
10.4 Using third-party tasks
247
247 250
CONTENTS
Defining tasks with Checkstyle
10.5 Notable third-party tasks 248
248 ✦ Torque–object-relational mapping
xiv
10.6 10.7 10.8 10.9
The ant-contrib tasks 253 Sharing task definitions among projects 258 Best practices 258 Summary 259
11 XDoclet 260
11.1 Installing XDoclet 261 11.2 To-do list generation 261 11.3 XDoclet architecture 262
XDoclet’s Ant tasks 263 ✦ Templating How XDoclet works 265 264
11.4 Writing your own XDoclet template
265
Code generation 267 ✦ Per-class versus single-file generation 272 ✦ Filtering classes processed 273
11.5 Advanced XDoclet 273
Custom subtasks 274 Creating a custom tag handler 274
11.6 The direction of XDoclet
275
276
XDoclet versus C# 275 Looking into Java’s future: JSR 175 and 181
11.7 XDoclet best practices
Dependency checking
276
276
11.8 Summary
277
12 Developing for the web
278
12.1 How are web applications different? 279 12.2 Working with tag libraries 280
Creating a tag library 280 ✦ Integrating tag libraries Summary of taglib development with Ant 287 286
12.3 Compiling JSP pages
288
289
Installing the task 289 ✦ Using the task JSP compilation for deployment 291 Other JSP compilation tasks 292
12.4 Customizing web applications
292
294
Filterset-based customization 292 Customizing deployment descriptors with XDoclet Customizing libraries in the WAR file 297
12.5 Generating static content
297
298
Generating new content 297 ✦ Creating new files Modifying existing files 299
CONTEN TS
xv
12.6 Testing web applications with HttpUnit
299
Writing HttpUnit tests 300 ✦ Compiling the tests 302 Preparing to run HttpUnit tests from Ant 303 Running the HttpUnit tests 303 ✦ Integrating the tests 304 Limitations of HttpUnit 306 ✦ Canoo WebTest 306
12.7 Server-side testing with Cactus 310
Cactus from Ant’s perspective 311 ✦ How Cactus works And now our test case 314 ✦ Cactus summary 314 313
12.8 Summary
315
13 Working with XML
317
13.1 Preamble: all about XML libraries 318 13.2 Validating XML 319
When a file isn’t validated 320 ✦ Resolving XML DTDs Supporting alternative XML validation mechanisms 322 321
13.3 Transforming XML with XSLT
323
Using the XMLCatalog datatype 325 Generating PDF files from XML source 327 Styler–a third-party transformation task 327
13.4 Generating an XML build log 327
Stylesheets 328 ✦ Output files 329 Postprocessing the build log 330
13.5 Loading XML data into Ant properties 13.6 Next steps in XML processing 332 13.7 Summary 332
331
14 Enterprise JavaBeans
14.1 EJB overview 333
333
The many types of Enterprise JavaBeans 334 EJB JAR 334 ✦ Vendor-specific situations 335
14.2 A simple EJB build 335 14.3 Using Ant’s EJB tasks 336 14.4 Using 337
Vendor-specific processing 339
14.5 Using XDoclet for EJB development
340
343
XDoclet subtasks 341 ✦ XDoclet’s @tags 342 Supporting different application servers with XDoclet Ant property substitution 343
14.6 Middlegen 345 14.7 Deploying to J2EE application servers
348
xvi
CONTENTS
14.8 A complete EJB example 349 14.9 Best practices in EJB projects 354 14.10 Summary 354
15 Working with web services
The SOAP API
355
357 359
15.1 What are web services and what is SOAP? 356
357 ✦ Adding web services to Java
15.2 Creating a SOAP client application with Ant
357
Preparing our build file 358 ✦ Creating the proxy classes Using the SOAP proxy classes 361 ✦ Compiling the SOAP client 361 ✦ Running the SOAP service 362 Reviewing SOAP client creation 363
15.3 Creating a SOAP service with Axis and Ant 363
The simple way to build a web service 364
15.4 Adding web services to an existing web application
Configuring the web application 367 Adding the libraries 368 Including SOAP services in the build 368 Testing the server for needed classes 369 Implementing the SOAP endpoint 370 Deploying our web service 370
367
15.5 Writing a client for our SOAP service
371
372
Importing the WSDL 371 ✦ Implementing the tests Writing the Java client 375
15.6 What is interoperability, and why is it a problem? 376 15.7 Building a C# client 376
380 Probing for the classes 377 ✦ Importing the WSDL in C# 378 ✦ Writing the C# client class 379 Building the C# client 379 ✦ Running the C# client Review of the C# client build process 381
15.8 The rigorous way to build a web service 381 15.9 Reviewing web service development 15.10 Calling Ant via SOAP 383 15.11 Summary 384 382
16 Continuous integration
386
387
388
16.1 Scheduling Ant builds with the operating system
The Windows way 387 ✦ The Unix version Making use of scripting 388
CONTEN TS
xvii
16.2 CruiseControl 388
How it works 389 ✦ It’s all about the cruise—getting the build runner working 389 ✦ Build log reporting 395 Email notifications and build labeling 396 CruiseControl summary 396 ✦ Tips and tricks 396 Pros and cons to CruiseControl 396
16.3 Anthill 397
Getting Anthill working Anthill summary 400 398 ✦ How Anthill works 399
16.4 Gump
401
404
Installing and running Gump 401 How Gump works 403 ✦ Summary of Gump
16.5 Comparison of continuous integration tools 16.6 Summary 406
405
17 Developing native code
407
17.1 The challenge of native code 407 17.2 Using existing build tools 408
Delegating to an IDE 408 ✦ Using Make 409 411
17.3 Introducing the task
410
Installing the tasks 410 ✦ Adding a compiler A quick introduction to the task 411
17.4 Building a JNI library in Ant
412
Steps to building a JNI library 413 ✦ Writing the Java stub 414 Writing the C++ class 415 ✦ Compiling the C++ source 416 Deploying and testing the library 419
17.5 Going cross-platform 422
Migrating the C++ source 422 ✦ Extending the build file Testing the migration 424 ✦ Porting the code 424 423
17.6 Looking at in more detail 425
Defining preprocessor macros 425 ✦ Linking to libraries with 426 ✦ Configuring compilers and linkers 427 Customizing linkers 428
17.7 Distributing native libraries 429 17.8 Summary 430
18 Production deployment
431
432
18.1 The challenge of different application servers
Fundamentally different underlying behaviors 432 Different Java run-time behavior 433 Coping with different API implementations 434
xviii
CONTENTS
Vendor-specific libraries 436 ✦ Deployment descriptors Server-specific deployment processes 436 Server-specific management 436
436
18.2 Working with operations
437
Operations use cases 437 ✦ Operations tests 437 Operations defect tracking 438 ✦ Integrating operations with the build process 438
18.3 Addressing the deployment challenge with Ant 440
Have a single source tree 440 ✦ Have a unified target for creating the archive files 440 ✦ Run Ant server-side to deploy 441 ✦ Automate the upload and deployment process 442
18.4 Introducing Ant’s deployment power tools 442
The task 442 ✦ The task Remote control with 443 443
18.5 Building a production deployment process
446
The plan 446 ✦ The directory structure 447 The configuration files 447 ✦ The build files 447 The remote build.xml build file 447 Writing the build file for installing to a server 449 Uploading to the remote server 450 The remote deployment in action 454 Reviewing the deployment process 455
18.6 Deploying to specific application servers
456
459
Tomcat 4.0 and 4.1 456 ✦ BEA WebLogic 458 HP Bluestone application server 458 ✦ Other servers
18.7 Verifying deployment
459
460
Creating the timestamp file 460 Adding the timestamp file to the application Testing the timestamp 462
18.8 Best practices 462 18.9 Summary 463
Part 3
Extending Ant 465
19 Writing Ant tasks 467
19.1 What exactly is an Ant task? 468
The world’s simplest Ant task 468 ✦ Compiling and using a task in the same build 469 ✦ Task lifecycle 469
19.2 Ant API primer 470
Task 470 ✦ Project 471 ✦ Path 472 ✦ FileSet 472 DirectoryScanner 472 ✦ EnumeratedAttribute 473 ✦ FileUtils 473
CONTEN TS
xix
19.3 How tasks get data
474
Setting attributes 474 ✦ Supporting nested elements 480 Supporting datatypes 481 ✦ Allowing free-form body text 482
19.4 Creating a basic Ant Task subclass 483
Adding an attribute to a task 483 ✦ Handling element text 484
19.5 19.6 19.7 19.8
Operating on a fileset 485 Error handling 486 Testing Ant tasks 487 Executing external programs 487
Dealing with process output 490 ✦ Summary of native execution 490 490
19.9 Executing a Java program within a task 490
Example task to execute a forked Java program
19.10 19.11 19.12 19.13
Supporting arbitrarily named elements and attributes 493 Building a task library 495 Supporting multiple versions of Ant 497 Summary 497
20 Extending Ant further
20.1 Scripting within Ant
498
499
500
Implicit objects provided to