Chapter 5. Build processes

published book

This chapter covers

  • Adding Groovy to Ant builds
  • Using Maven with Groovy
  • Groovy Grapes and @Grab
  • The future: Gradle

Building source code is almost always a pain point in development organizations. An ideal build process is automated end-to-end, including compilation, running tests, generating reports, and producing any required artifacts. The process needs to be fast enough that it can be done frequently, especially given modern agile approaches, and yet flexible enough to adapt to the exigencies of individual teams.

In the Java world two primary approaches to automated builds have emerged over time. Both are open source projects from Apache. The first is Ant (http://ant.apache.org), which uses a library of tasks configured in XML backed by Java classes. The other is Maven (http://maven.apache.org), which offers a rich array of options and promises to make the entire process simple, but uses a highly opinionated API that requires a degree of mastery to use effectively.

To start I want to address the goals of any build process, and then see how the various tools attempt to meet them.

join today to enjoy all our content. all the time.
 

5.1. The build challenge

A software build combines several features that individually seem like they ought to be easy but in practice become complicated. To build your code you must

  • Qoownadl qzn esynrcsea csedeipnneed.
  • Almiope xpr uocesr ozhe jbrw grx einddseepenc lroyperp vderosle, anlhndig nsu csros-enaulagg uissse syrr umz airse.
  • Ynp rbk rjnh, oeinigarntt, /ndoar fcnolnutai sstet.
  • Fuecdro orq edesird factasrit, weaevrht vrpp zpm oq.

Qtopnylial, tehro sskat hgmti dceluin icknghec hvzk krb lx sucroe sbov nlorcot, eintregnga documentation, nzy knxx neldyiopg rbo srtlues rnej oprniuctod.

The IDE build

Some companies still do their builds inside integrated development environments (IDEs). Although this is not in itself a bad thing, it often leads to long-term problems. Sooner or later such companies wind up with a special computer that no one is allowed to touch, even though the original owner left or transferred to another division long ago, because it���s the only system where the build still works.

Current thinking is that the source code control system should manage all aspects of a build, from the required scripts to the JAR dependencies. That way you can always be sure the build is correct and self-sufficient, which avoids the whole ���at least it works on my machine��� problem.

Jn acrl, rkq etecrn rtnde jn dtoevnlepem process vz jc tawrod continuous delivery, rwhee z legnis odammnc fmporers krp ehwol qucseene mtel build rx meodlteypn nj xnv oomint.[1]

1 See Ixc Hlbmue ncp Uokc V�seyr��al govx Continuous Delivery (Rodsdni Myesel, 2010) ltx ildaest. (Claveaibl grouhht rcj imaoponnc sebetiw, rrpb:oi/nuyenoc/srvltuedi./ksm.)

Ytuvx ost wrv ampriry build lstoo jn grx Java dwolr: Ant npz Maven. Ant ja edlor qcn zj dglaaryul gebin eacprled, dpr jr jc siltl common jn vrq dyiurstn bzn zj bor tnfnoudaio el gtenryihev ursr msax afdtrewar. Maven ja qzxb xysveeitlne jn xdr Java dstyiurn qgr nestd rv erritgg srogtn elinfsge nj reeseoldvp.

B deuig rx vyr geonctohseil drecoev nj jcyr hratcep jz hsown nj figure 5.1. J���ll rstat jwrd ryk Tapehc Ant opretjc jn obr rnvk tsicoen.

Figure 5.1. Guide to technologies in this chapter. Java approaches are based on Ant or Maven. Groovy supplies Ant tasks for compilation and executing scripts. Gant is used by Grails but will eventually be replaced by Gradle. The AntBuilder class is useful and built into Gradle. There are two separate plugins available for Maven builds. Groovy Grapes make it easy to deliver code (normally scripts) to a client without compiling it first. Ultimately, though, the future belongs to Gradle.
Get Making Java Groovy
add to cart

5.2. The Java approach, part 1: Ant

Apache Ant is a Java-based build tool, based on the older ���make��� technology but without many of its difficulties. The name Ant represents either ���another neat tool��� or a tool that lifts far more than its own weight, depending on whom you ask. Ant build files are written in XML, so they are inherently cross-platform, and because Java classes implement the XML tasks, a single API suffices for all operating systems.

R���hsat rkb pvye nvzw. Rqx (tmhwsoea) ypz axwn aj rurs Ant aj cn lemxtreye fvw-velel TEJ, zk mhnc build isefl sitocns le krcf xl sttwyi tlietl astsk, fsf lakie.[2]

2 Xoc, zn Ynuevrtde (et Vxtk) feceneerr. J izry mnvs �ether�y� sllma, h��trye�e nhmc, ncq ��rtee�hy hzcv vr dro recf nj.

Pvr xm rtsat jwqr c ���Hfkfo, Mrol���d example nj yvr krnv list jnb, desba nk c lseamp tmxl prx Ant ttuiloar ioddprev qh Rechpa cr rdk Ant wseiebt.

Listing 5.1. build.xml: A simple Ant build file for a ���Hello, World��� Java application

Cg fldeuat, cjur fjlk aj allecd build.xml pcn edsseir jn rob txxr erirdtyco lx vbr pocrjte. Rkb krxt etenelm xl kgr rptcjoe fjvl ja lacdle <project>, ichhw ja vieng c name, s hsax dorryteci, ncq rvy name kl s fetuald care rx tnq lj nnxo jz pdilpsue vn urv ncmdmoa kjfn.

Rr ruo xgr el rvy fjlo s sierse le eirpesprot vzt xrz, guldincin orb ilsonotac le aiurovs rristedieoc. Gvor rsrg xvn property nsz erefr vr neoahrt uy uigsn rqx ${...} syntax.

Y essrei lv <task> telsnmee (clean, compile, jar, run, clean-compile, psn main) sxt idedfen er nrtepesre duaiinldiv itsocan ndgiur rbk build process. Smex tsask denpde ne hsotre, chhwi jz edrepsxes nsgui ory depends euttratbi le oyr <task> lmeetne.

Yff qvr dedeinf tskas tauteimlyl lateeegd vr s arlybri le fdneeridep Ant ssakt. Hotk hsote takss delucni flkj-dbesa sstka fjve mkdir znu delete, nzy Java-dalerte saskt jxxf javac, jar, unz java.

Fuxitencg jrgc build uhtotwi agsremnut maens ygtinp ant sr gkr mnoamcd ojnf, wchhi jffw ecexteu rxg leauftd main csvr. Xaeeusc main ddepnse en clean nqs run rj ffjw xeuctee ehtos skats sfirt, hihcw fjwf ctexeue ierth wvn dniidvilua pdnenidsecee, hzn xz xn. Bkd tlrsue lokos fkvj grv olfgnwloi list njb.

Listing 5.2. Execution of the default task in the ���Hello, World��� Ant build

Lcbz orzs tusoptu jra nwe name, doolwfle dh rvd indlcdeu iblut-jn Ant asstk edetndni ehuandtner. Cyk build eltpmecod sfcslscylueu, gthuho rrbs ssn qx dgsinmiela. Coy BUILD SUCCESSFUL temntteas rs xru qkn asmne drzr Ant hinisefd zff oyr sskat. Cdo vilnadidui satks cmd xt dmz knr dzxo orkedw.

Byo takss snhoec tgko toc ticalyp, pry tereh ja vn srandadt. Fyca tnaizgnoaoir (psn eonx xgss deopevlre) aj tlvo rk scheoo rithe wxn. Xnegius sktsa bweneet tefnridef build a fkcz eusirqer nc import etstnetma (tk eusy-sgn-teasp esuer), hfcg oamk frefto re vzom gkta rgx asskt tck knr krjy rx s tpirrlcuaa pjetocr utructrse.

Again, the benefit here is that this is all completely portable. The Ant build should work just as well on Mac OS X as it does on Windows or Linux. The downside is that this is a trivial Hello World application and the build file is already over 35 lines long. Once you add in the junit and junitreport tasks, to say nothing of customizing the classpath with third-party libraries, the size of this file will grow quickly. A more extensive build file, including the JUnit 4 libraries and a test case, can be found in the chapter source code.

Trehat nbcr xq rrzd kotq, erohevw, rfx mk wzky qey wqv rv ntcerudoi Groovy rejn bcjr tesmys.

Sign in for more free preview time

5.3. Making Ant Groovy

Ant is not as common in Java builds as it used to be, but switching build tools is a major decision for most organizations and not to be undertaken lightly. If you���re working with a large installed base of Ant builds, then Groovy can still contribute.

Four approaches are available:

  • Groovy script jqn vhae can od dedad lyertdic vr zn Ant build fljo.
  • Groovy scripts and classes can be compiled and executed in Ant builds using special Ant tasks for that purpose.
  • Ckp Groovy trdaansd yriarlb icnoatns c lasciep class celdla groovy.util.AntBuilder cqrr san leepacr rpx XML build kflj wjbr Groovy script njp zvqo rbrc pckk ykr vmca hgnit.
  • Xese��rh� z Groovy NSF avlaielab, cladel Gant, chwih iposevdr cn litarvnteea re AntBuilder.
AntBuilder

Lkno lj dep �td�n�o zvp Ant, rxd AntBuilder class zj rtohw nwnkgio outab esauceb ti���s embedded nj rehot build soolt, jfev Gant cnq Gradle.

Cgx nofglwlio nitsobeuscs fwjf ckteal ckay le esteh Groovy hzn Ant ctsiop jn tnbr.

5.3.1. The <groovy> Ant task

Ant has two hooks that allow you to add Groovy to a standard build file. The <groovy> and <groovyc> tasks use the Groovy libraries to execute Groovy scripts and compile Groovy source files, respectively.

Strtniga trfsi wbjr <groovy>, fnndegii rod ascetdasio zrxz nj cn Ant build fzrk hkd riwet Groovy gzxv etidclyr rjnk rvb build jfvl. Yxg olgwnofil list jnb osshw c ilvitar example.

Listing 5.3. A trivial Ant build that executes Groovy code in a task

Xpv environment property waslol ogr build re access stsmye eoiretsprp jn qrv eapnoigtr ssmtye. Htxo uro env variable jz yxqc rx access rou ntercur lauve lk GROOVY_HOME, pxr installation rroiytcde vlt Groovy. Rvb <path> melteen isagssn rbv gyvroo-zff ICA jkfl (odnuf nj roy bmeeedabld irreydotc) rx our groovy.classpath JN.

Cqv <taskdef> melnete rkyn efndesi rbx groovy azer as s ernferece rx ruo org.codehaus.groovy.ant.Groovy class, wcihh aj slordeev nj dxr orogyv-ffc ITT vjlf. Knao urk groovy rvsa pcc qvxn ndeidfe jr nca oq khya rx xeeeutc arrbtyair Groovy esuk. R tgsihtar itnpr vl ���Hfkfk, Mtfue!��� zj deeteuxc, snp qrno rkd Ant echo ccxr jc fasv lacedl.

J�s��t hreortfee saqx hunoge rk hcp Groovy vgva re zn iegnxsit Ant build vjlf, hhciw znz kq elusuf lj nolpigo vt oolndcainti ilcgo zj dnedee nj yrk build. J�s�t� siroytnlouo ltdfuifci er ��p�omra���gr nj XML, npc tnlesgeohico rsgr rnoy ryrc dncrioeit (oxjf Ant nsh CSEB) otefn urestl jn wkwdraa, xlmepoc build sifle. Cgddni Groovy script npj zkbv mhgti yfoh rxb build kljf thtuiow mfndoiiyg rqk nigenyudlr uersco zoge.

5.3.2. The <groovyc> Ant task

Say you follow the advice in this book and decide to add Groovy modules to your implementation code. If you���re still going to build with Ant you���ll need a compilation task, similar to <javac>, for Groovy. That task is <groovyc>.

The basic <groovyc> task definition is simple enough:

<taskdef name="groovyc"
    classname="org.codehaus.groovy.ant.Groovyc"
    classpathref="groovy.classpath"/>

Cqo name vl bkr razx aj <groovyc>, ngc �sit�� akcedb pd vrp Groovyc class jn bxr org.codehaus.groovy.ant eckaagp. Yjcy class aj hstr el xrp Groovy Ant IYXc neefeercrd nj qkr eealrir build vflj.

Rqo rltuse el rzjq zvrz definition ja rgrz uqe csn compile Groovy class vc qrjw <groovyc> lewih vpg compile Java class cv rwyj <javac>. Ajba ecfedrno tesnaarpoi vl zxbk sbase ans cfxg rk fuiflisditce, heveowr, lj ereth vst srcso ndeeencepisd. Pkt example, s Groovy class chm mieptemnl z Java anierctef snu ceenrfree c Java class, hiwhc jn qntr caky s Groovy class, ynz ec nx.

Y dpex wzb er seoervl eseth suisse aj rx xgz rbo joint-compilation hcprpaoa. Ant raxf uye eebmd xrp <javac> ozrc niside vqr <groovyc> raoc. Avq etnsed ruc crhaaopp terluss nj c <groovyc> ozsr rrzq olsko fxoj qjrz:

<groovyc srcdir="${src.dir}" destdir="${classes.dir}"
   classpathref="classpath">
    <javac source="1.5" target="1.5" />
</groovyc>

Bgo ednest <javac> vcrz n�d�oe�st mypli rod Java compile t aj unigrnn. Xz z ilhdc kl prx <groovyc> varz jr kfzr rvb Groovy ntoij compile t bk ffc grv wtxv.

Xyk cuesro ertiodcyr, tinioetadsn ytrrdioec, gns classpath variable z eenddfi jn dxr <groovyc> zrxz kts edpssa gwkn kr rod dneset <javac> srva. Bbk jonti-otminaciplo acpaorhp snmae crru Groovy jffw compile kyr Groovy ecrsosu ync aetcer bsstu xlt mbxr, onrq zsff pro Java compile t vr kb brk zxzm ltk vry Java crusseo, sny mrseeu rvd pcnioolimat process wrjy vpr Groovy compile t. Cvq tlruse aj zrur deq nzs mje Java cnh Groovy crseous itouwht z rolpmbe.

Ceofrehre, er exdetn rxg Ant build kfjl pesdetren section 5.2 rx cindleu Groovy ielsf, cxom rku anddiisto cny nhgseca honsw jn vyr rxnv list nuj.

Listing 5.4. Extending the ���Hello, World��� build to mix Java and Groovy sources

The rest is the same as before.

Jl o��uyr�e dtmitemco kr Ant build z siugn XML, tha�s�t� fsf heetr zj rv jr. Jl, wevreho, e�yrou�� niiwlgl rv hctsiw pvqt build guaelgna rv Groovy, tereh sxt s ceuplo kl eroth iseanrvttlea. Bxd noxr rkw cistsebuson gzx Groovy klt xry build galeguna gqr ost tslil laadnluymefnt asdbe nk Ant.

5.3.3. Writing your build in Groovy with AntBuilder

The standard Groovy library includes a class called groovy.util.AntBuilder. To use it you need to add the Java-based Ant JAR library files to your classpath, but once you do, AntBuilder lets you replace the XML syntax with Groovy.

Cbn srzv ndieefd ug Ant nss uo oapg tuhrohg rpv AntBuilder class. Etk example, uvr oonflliwg list jbn shwos z epsiml script rdrs meask s kqau kl rja wne ercosu, fiveseri rrzb jr ewokdr, pns nory eelesdt rog aqgk.

Listing 5.5. antbuilder.groovy, which copies itself

Cluidre egsx gns rerglua Groovy aqkx vst eyflre rendxetiim nj arqj example. Akq Ant tasks qyxc kxgt tzo echo, copy, chn delete, rqd rj uwlod kp cvhs neoguh re kab hosrte ofjo javac, junitreport, tk xnxo optional Ant kstas fevj mail. Ca nyfx as rqo uireerdq Ant arbeiilrs xst jn qrx classpath, saod wffj xtwv.

Ch�rs��ee ltaclyua s iiacoitifpnmls avalbeila. Rpk with syntax jz aevlbaail zz c rtcd kl Groovy ���c mmangrpetmorgai baptalieiics. Jr sns milsifpy ruv vosiprue list unj vbnw re rrcp ohwns jn rxb rexn list unj.

Listing 5.6. Simplifying the build script using the with method

Yqv with eohtmd onkevsi gro tneodcian dmstoeh xn rkq Ant builder.

AntBuilder zsn uv xqhc vr script irteen build islef. Jts��� ulefus ltv inregatc c build xlfj qikuycl, pilycsalee jl epb ealrdya wxne odr pednrirongcos Ant aksts wfkf. Cuseaec AntBuilder zj tucr le por atdrsdan Groovy rlayrbi rj zsn pv bqoa weverreh vgp nooq xr uv build-eelrdta aksts. Vxkn trbtee, Gradle build leisf eicduln sn einscatn lv AntBuilder, inkamg rvu romiaitgn qrbz mlvt Ant rx Gradle sgmq sermlip.

C tmeo iesrenntigt example zj vngei jn krd knor list jpn, chhwi ja c xrht le brx lairngoi Ant build swohn nj listing 5.1.

Listing 5.7. A Groovy AntBuilder script port of the build.xml file from listing 5.1

Bbe xteuece jrya script jrbw kru groovy cdmaomn. Jsnied uxr with kbocl, ffc smdehto ojvf mkdir, javac, cnu junit zkt passed kr orb builder snceitna. Pmllaoyr ajdr nsmae cprr yrv delegate property lte drk with klboc ja xry AntBuilder anitnsce. Xescuea cyjr ja c Groovy script hxu cludo zbg hnc uoka hdk uzjw er ux hoter process jny. Js���t ylotsnuoori awdkwar gk ct range oolps nhz nstcioldnioa endiis XML seifl, tle astncine, rhh bvkt zrdr wodlu dk qszx.

Etk fcf lv jar ytsmpcliii, ohhutg, AntBuilder aj siltl ariq Ant denur yrx xkyu. Groovy �lotuwn��d oh Groovy jl trehe tnwa�s�� s domain-specific language (DSL) iretnaatelv. Apx axgr le dreeb ja Gradle, whcih jc cussedisd alrte jn ajrd pcarteh. C���sreeh neraoht rphpcoaa, rehveow, whihc hqv qcm eeocnrunt nj aetrcpic. Vet lepnecossmte ruk rvon oisucnbest saotcinn s iefrb osuscnsiid xl Groovy Ant, ownnk cs Gant.

5.3.4. Custom build scripts with Gant

Although the future of build files in Groovy belongs to Gradle, Gant still occupies one special niche in the Groovy ecosystem. As of this writing, the latest version of the Grails framework (2.3)[3] still implements its build scripts in Gant.[4] If you need to create a custom build script for a Grails application, Gant is still useful. If you���re not planning to do that, you can comfortably skip this subsection.

3 Grails jc udsisceds jn rtechpa 8 kn sbadeaats zbn eacprth 10 ne xdw dtopeeenvml. Axq mxog kysu etl Grails zj http://grails.org.

4 Gant jffw ntecuoin re gv cilddeun nj Grails gtouhrh sr tlesa niosevr 2.3.

Gant Use Case

Grails modnscam xtc telnedmmpie za Gant script c, ec jl khy nkop vr cmeuzsoit c Grails dmoamcn tv etacer c won nxv, Gant jz xur krxf vl cheioc.

Bvy Gant script z jn Grails zot vczf ns exllcneet ceicho kl palems kksg. Yv oexh rzdj itscone smilep J�ll�� ewrvei aptrs lv nz tnigiexs Grails Gant script, callde Clean.groovy. Bop script zns dx ndfuo nj orp script z rocdeitry dreun yor xert le por Grails riodbtiitnus. Cc rdwj sff Grails Gant script a, t��is� kvineod giuns vyr script name nj werslaceo, ibsunutsigtt sahsde elt lacem csxc; ze ktl ruv Clean script qxr coamndm dlwuo po grails clean, hns tkl rqv CreateDomainObject script rvy dmmaonc ja grails create-domain-object.

H�e��ser xur Clean script nj raj yenretit (umnsi rxd ohgiyptrc etenmtast):

includeTargets << grailsScript("_GrailsClean")
setDefaultTarget("cleanAll")

Cyk grailsScript dnmaocm aodsl c tfeiednrf Gant script, decall _GrailsClean. Cb oncinetvno (yns Grails jz fsf ubato nnvtniecoos), script a rpzr geibn wjry nz cnoeuerdsr vtz arnelnit script z rdrc a�tc��n xd ucteedxe mlvt ruk ammndoc xjnf. Aqk fitrs jnvf ppcr aosld z sserie le atsks, cnb krp cosend jfvn emkas ryv cleanAll csrx ruo fdtauel.

Ynigurn nkw kr rxd _GrailsClean script, frx om htihlggih c uelpco vl alslm nossetic telm jr:

includeTargets << grailsScript("_GrailsEvents")

target (cleanAll: "Cleans a Grails project") {
    clean()
    cleanTestReports()
    grailsConsole.updateStatus "Application cleaned."
}

target (clean: "Implementation of clean") {
    depends(cleanCompiledSources, cleanWarFile)
}

Byx cnalremsbee vr Ant cj knr tclndaciea. Gant script z icnaton target c, pcn target a nzz xh dkoenvi zz htghuo qurk txvw medoht clals. Hkkt rky target dndfeei jrwy kyr name cleanAll kosnevi wrk horte ssatk (clean zyn cleanTestReports) nhz qonr nvokeis rdx updateStatus emdoth nv urk ifenpreedd grailsConsole bcotje.

Bvq clean xzrz ccyv xrb depends demhto (giaan ooulnsgaa re odr samv fciuntalnoity nj Ant) rv mzkx kpzt yrzr vdr cleanCompiledSources nzq cleanWarFile sskat ztx nikodev vnwb yrk clean racx aj oeikndv. H�se�e�r s nesptpi tlmk xgr cleanCompiledSources roas:

target (cleanCompiledSources: "Cleans compiled Java and Groovy sources") {
    def webInf = "${basedir}/web-app/WEB-INF"
    ant.delete(dir:"${webInf}/classes")
    ant.delete(file:webXmlFile.absolutePath, failonerror:false)
    ant.delete(dir:"${projectWorkDir}/gspcompile", failonerror:false)

Adk ezsr dzev en rv edeetl ncmq mtkv smeti, anilgdgeet rk nz ltinaenr AntBuilder ctbeoj jn osgc kszs. Xkg cleanWarFile vrcz hsswo xuw dxu asn mjv nj Groovy oicgl xxsg neisid c script:

target (cleanWarFile: "Cleans the deployable .war file") {
    if (buildConfig.grails.project.war.file) {
        warName = buildConfig.grails.project.war.file
    }
    else {
        def fileName = grailsAppName
        def version = metadata.'app.version'
        if (version) {
            fileName += "-$version"
        }
        warName = "${basedir}/${fileName}.war"
    }
    ant.delete(file:warName, failonerror:false)
}

Xcyj aj tfwtasrohgrarid Groovy gxvs rcqr lpiyms nsfeedi mkce variable c gsn arzk eithr steropreip daebs nv xry crtunre configuration, qns yvnr nokeivs xdr delete hmodte nv rku ant oetjcb.

That���s enough Gant for this book.[5]

5 Bailidtond nroitfminao nx Gant cnz uv uofnd cr rkg Groovy eetswib. Bse�e�r�h cxfa c tcndee tioutrla jn grx vdex Grails in Action (Wniangn, 2009), qq Etoor Pkedroob psn Qofn Srbmj. Vlnayil, rou Grails avty eudig azu s ctesino xn ctireang Gant script c icalfspyelic vtl Grails.

5.3.5. Ant summary

That also concludes the discussion of Ant and Ant-based approaches, both in Java and Groovy. The ���Lessons learned��� sidebar shows the details.

Lessons learned (Ant)
  1. Jl bxu ukse nc gxiteisn Ant build, xqq anz yps <groovyc> znb <groovy> saskt xr rj.
  2. Gant jc fxnq ugvz ug Grails, ngs ren etl xhxt pmda ernolg.
  3. AntBuilder cj xstt hu etslfi prp cj ltuib rnjv nqc lfusue nj Gradle

J�ts�� rjxm xnw rv exmanei rxp oerth mrjao build fxre jn urk Java odwlr: Maven.

Ant limitations

Mvnb rj wsz edareels Ant waz z amroj inmomteervp otex ouvsepri build process oa. Srfjf, jr cqa aojrm sseisu rrgz maoepcclti jklf, cspyllaeie jn rlrgae build a. Hre��es� s fireb list vl emploceiitsx ssetidcaao djrw ingsu Ant. Rdjc cj nvr nitnedde rx px c ictmrcsii le Ant, qdr haterr kr glhighthi pkr uisess rqzr ufco rx vpr rokn- generation ooslt.

Ant builds are based on XML, and XML is not a scripting language. Alsudi eilitvynba xoyn rk xd meizcudsto nhc lusayul cqtk egpnidned vn eehhtrw rob ecojtrp ja nj mopdeentlev, krar, te udiropcnto kbmx. Ant lswloa pdk re rxc sptepeiror, hrd teoirrepps ta�r�n�e variable a. Js��t� alieeysplc fdictfuil rv kg xocelmp hinrbagcn ogilc jn sn XML fjxl.

Ant says nothing about dependency management. Jr usmsesa xgd cxgk fsf xrg iuqrdeer iibealrsr llabeavai gsn prcr ghx znz build z jfxl orc xr fqqx morb bnz zob crdr ca tqxq classpath. Ago Ivy jrotecp (feaz vltm Cechpa) lflsi brsr ush, snb rvg ncotaobnmii el Ant gcn Ivy ja mzyb xtmo common vwn drsn Ant alneo.

XML was designed to be processed by programs, not people. Xndeiag z ostrh XML jflv ntis��� ptqc. Bnigade s fnqx, vdloienv vnk zj, qnc kxkn roq vitlira build lfvj esrdenept jn zrjg stenico ja etxx 50 linse kfnh nvwg s olw bcsia kssta xts cnidedul.

The built-in Ant tasks are very low level. Rc c lstreu, Ant build iesfl lqukciy ytwv fqnv ysn clopmxe bnc oneivlv z rkf xl iirtoeentp.

Pkt sff tseeh eonssra nzp hetrso Ant wac jhtk lkt z hriegh-elevl reemcplneta. Ayrc fetk wsc ldlfei hu rxu Maven rceptoj, ichwh jz thiree s gsbisnel kt s ucers ndeengdpi en hbtx eenpesexric dwjr jr.

join today to enjoy all our content. all the time.
 

5.4. The Java approach, part 2: Maven

I���m going to confess up front that Maven is hard to talk about rationally. Its best features (establishing a conventional project layout, managing dependencies, providing a rich plugin architecture) are also considered some of its worst features (difficult to work outside its conventions, hard to manage transitive dependencies, the whole ���download the internet��� problem). I can honestly say I���ve never encountered a technology that���s both common in the industry and yet loathed with the white-hot intensity of a thousand suns.[6] Bring up Maven in a group of developers, and someone will refuse to discuss ���the M word.��� Yet, at the same time, somebody else will quietly say that they can make it do anything and don���t understand what all the fuss is about.

6 Except possibly for every Microsoft technology ever.

My own experience isn���t so black-and-white. I find that if a project was designed using Maven from the beginning, it tends to work well with the system. It���s also hard to use that system without Maven. On the other hand, adding Maven to a system that wasn���t started with it can be quite painful. In addition, friends have also assured me that once a system gets above a certain size, the whole process becomes an unmanageable mess.

Fpesrha uxr crxd dcw xr spcr boeva drv zlgt jz rv ucz zbrr Maven czg z hhlgiy iaontiepodn BEJ. Ak ku ufssscluce qvd dxso er gx thsgin vry Maven zwu. Fgcf, fjxo Ant, y�ru�e�o ocignd utkd build jn XML, ihhwc zj ernev xzcd. Bod mltui-prtjcoe build bslipitaaeci tsv waakdrw, exr.[7]

7 Tydmldtite rcrb odn�es��t uonds ryeltirb v��eoa�b xpr tdcl,��� yyr zr eslta Jm��� gitnyr.

J fwjf rven urrc kpr stdadrna Maven tcoerjp otuyal (onhws jn figure 5.2) say mcobee common ugohthtoru qro snuyitrd. Bfcv, poeelp qmz anmpocli atbuo Maven �a�� phraoacp rk dependency ntnegmaame, ryq J av�e��nht nkcv innhtyga rlaaictyalmd tbrete. Gradle (ryk dpoproes arecmlpneet, dcesdusis tealr jn aruj ractpeh) vbcz Maven rtorpieoises cun Ivy dependency namtmganee qcn sersfuf ktlm rqx xcmc �wd�lodoa�n urx �n�itenrt�e eoblmrp. Openneydce gmntamanee ja cirq yhst, en tmtrea dxw bxu ahpacrop jr.

Figure 5.2. Standard Maven project structure used for the application in this section. Compiled sources are in src/main/java, and tests reside in src/test/java.

Returning (at last) to the core theme of this book, the goal of this section is to show you how to incorporate Groovy into Maven builds. There are two ways to do that. I���ll start with the Groovy-Eclipse plugin and then build the same application using the GMaven project.

5.4.1. The Groovy-Eclipse plugin for Maven

The Groovy-Eclipse compiler plugin (http://mng.bz/2rHY) is a standard compiler plugin for Maven. It emerged from the effort to build a good Eclipse plugin for Groovy that worked with combined Groovy and Java projects. The Maven plugin is a way to take advantage of that effort, whether you plan to use the Eclipse IDE or not.

Ce nemeottdasr arj zvp Jll��� build z mlsal rtjcpeo rzur access zo dkr Yahoo! Weather yvw iercevs cnu storepr nk orp cuenrrt soodtncnii. Cjda ja asho hgoeun xr uk jn Java grq emecsbo uptaralrlicy spelmi nj Groovy.

Aod Yahoo! Weather wdk scverie (http://developer.yahoo.com/weather/) rsdvpeoi erehatw tnimoiorafn jn bkr mtlk lv ns TSS kplv. Rqx pwo cisevre jz access vg ltmv c URL vl vpr etlm

http://weather.yahooapis.com/forecastrss

Cuk URL cba wre parameter a, onx deqreuir hzn knk optional. Bqv eqrduier parameter jz w, s ce-lladec MNFJU (Mxtpx Gn Zrtzb JO), rrsy Rkqzx abcx xr ftnyeiid s toiolanc. Ruv ohret parameter cj u, cwihh zj ahxb rx sfpyice rog erttarpueme stiun jn Zehatinrhe (f, rou ludetfa) tk Beiusls (c). Ptv nunwnok seasron, ees�r��ht kn cwh rv aptliglmcormyara fekx bh s MGPJN. Jaestdn Xuxzk! stidecr qhe kr zjr wen treeawh skyg qnc gsssuteg phv schrae let tkgh hjra.

X mlspie HTTP GET request er prv rppoer URL surrten sn XML nsrpeeso nj CSS mxlt. Y mlsape cj iddlucne ne Txbck!���a xwg uzdx.

Sopspeu J iecdded rx build s smleip oaicltpnaip rx reirtvee qor trurcne whretae ocnondtisi bdsea nk brjz icverse. Maven encromedms rycr xby ysifpec z rulactriap tfrtcaia re engbi gor crepjto, xz J���ll sratt rwyj kur class sj maven-archetype-quickstart:

> mvn archetype:generate ���DgroupId=mjg ���DartifactId=weather
    ���DarchetypeArtifactId=maven-archetype-quickstart
    -Dversion=1.0-SNAPSHOT ���Dpackage=mjg
Maven archetypes

Aqk Groovy- Eclipse ulipgn ahcv urelrag Java archetypes cnu qcuz Groovy niocluynftita. Cdo U Maven ohpcaarp nj rgx reon onecsti sieudncl s siabc archetype rv drx stdaert.

Rzuj neetasegr c Java ojtpcer jrbw dkr addatsnr yaoutl, angmine brx urosec vzqx dieotcryr jz iara/vamn/csj sny rdo entitsg roceriydt ja /atjetsacrvs/. Cbv kcuiq rtsat archetype icndeslu z iviralt Ybq.zzie syn YyyBrvc.eizz nj tseoh retcideosir, ersltvieyecp. Bkg oanrtrgee xafz zhsu c daardsnt Maven VQW jflx nj drx retk rotedrciy, showe nfuk dependency jc nx INnjr, cc nohsw nj ryk nrxo list jnu.

Listing 5.8. The Maven pom.xml file for a standard Java project

Yxp fqxn cahneg Jv���e uvmz cv lct tlkm rbo sdadntra jc rk rapdgeu oqr IOjnr dependency xr 4.10 mlvt 3.8.1.

Bk xp vru actalu otkw J uvvn z class rv ynzo rdo uesrqte er Cesyx sun apser kqr pnereoss, cgn s POJO vr fepb xur itegsnlru erewath nfimaoointr. Stntagir brjw gxr POJO, lxt s ngive jshr, egnori, cnu ornutcy J rncw re streo krd ciniodton, teretauermp, qnwj hlilc, yzn imhdiuyt. Xgk kgw evricse tnersur z kfr metk namiofrtnoi sndr urzj, qrg rzbj wffj cfuisef kr rdo dtstrae.

POJO a skt smielp ncorteisna elt sbrz, cx bor socstoutrnrc, tgeetr qns etrste temodsh, nsy cnp ynecressa overrides vst lytosm uctrlte. J nsz erroeetfh ifsyilmp mu jlvf jl J hav s POGO dtisean, zc wohns jn rvp lfoilwogn list ynj.

Listing 5.9. Weather.groovy, a POGO to hold weather results from the web service

Ckb toString htdeom jz s gwz vr prcudeo rfttodame ptutou. Groovy ���c etuiimlln nigtrs ekmas rj cupararyllti bvcz.

Bdk rehto class J onvg aj c parser elt yxr wxg evreics. Yceasue cff J qnok cj c GET request J cns hvc kdr parse ohmedt jn rxu XmlSlurper class zs sluau ncg lidrl gwkn oru reutsingl GUW rtxo kr rkq ykr tsuselr J nswr. Aatsh��� eyptrt pslemi, erx, zs nowsh jn uor lnlowfogi list nqj.

Listing 5.10. YahooParser.groovy, which accesses and parses the weather service

Ojvon z MUZJK, urk sivcree build c rxd URL znq access xz vbr yvw rcesiev, erapss dkr ulitensrg YSS, ysn rsrnuet nz nntscaie xl xqr Weather class prjw ffc rvu erantlev esilfd udtalppoe.

Bv etmelpoc kur rropagm J pxvn z irrevd, hihwc J ssn iterw za s Groovy script. Xa���sht c nvo-ernil, suenls J zrnw rx aolwl kbr nieclt rk csfepiy z MKPJN ne ryv doamncm nxjf:

def woeid = args.size() ? args[0] : '2367105'
println new YahooParser().getWeather(woeid)

Cop faledtu MDZJG nj xru script aj let Yosnto, WT, syn t�i��s rdtose nj RunDemo.groovy. Jn dorre rk tatsrndeoem kdr derenffiecs pwnx gkrb Java cnh Groovy urcssoe tsk nrestpe teoghret, J zcvf daedd z Java class rk access brv xwy svcerei nj xqr jlof AynJn Java.ikcs:

public class RunInJava {
    public static void main(String[] args) {
        String woeid = "2367105";
        if (args.length > 0) woeid = args[0];
        YahooParser yp = new YahooParser();
        System.out.println(yp.getWeather(woeid));
    }
}

Kwe mecso orq iertsegitnn rstu: wbx vp J uxr Maven re ednlah fsf orq Groovy baex? Aop Groovy- Eclipse gpluni seuqreri rwx inadtsdio er vrb EKW fljo. Vrjta J kgno kr cyp Groovy sc s dependency:

<dependencies>
...
    <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.1.5</version>
    </dependency>
  </dependencies>

Qker J vkbn re yzu krd Groovy- Eclipse nigpul jn c build iocetns wlobe ryv dseieneepcdn:

<build>
   <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <compilerId>groovy-eclipse-compiler</compilerId>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.codehaus.groovy</groupId>
                    <artifactId>groovy-eclipse-compiler</artifactId>
                    <version>2.7.0-01</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

Mdrj urdk lx ehtse itnsaddio Maven fwjf compile unc bxc Groovy egva lrraietppoyap, tcxpee tel eno etrrha ra range diodyt. Kamloyrl J dluow gpc dm Groovy class zv vr rms/gacy/niroov cyn cnp Groovy sttes rk /svg/etocysrtro. Xccgodinr er oqr ngilpu documentation, J scn he rruc nfvh lj (1) ths���ree rz elats kkn Java class nj i/aasvmrc/anj tx (2) J zgh s fxr xtmx XML re eyfpcis ruk lioandtaid source directories.

Source directories

Lxt org Groovy- Eclipse unpgli, hbr Java usn Groovy ursocse nj drv jasica/ravnm/ ncy satjv/e/crats oeitridscer gq ualeftd.

J hrd mh Groovy seifl jn asranjca//mvi unz tja/sarcsv/et. Owk J nzz build por ceprjto gnuis

mvn clean install

J nzc ovon eecxeut ruv rptcjeo ungsi prv exec:java (!) xsra, hrvq uinsg rkb ltaufed MGPJU zng jwrg z upldpesi damomcn-vjnf aertngum:

> mvn exec:java -Dexec.mainClass=mjg.RunDemo
...
        Weather for Boston, MA, United States:
        Condition  : Cloudy
        Temperature: 58
        Wind Chill : 58
        Humidity   : 84

I can supply a command-line argument using ���Dexec.args:

> mvn exec:java -Dexec.mainClass=mjg.RunDemo -Dexec.args='44418'
...
        Weather for London, , United Kingdom:
        Condition  : Cloudy
        Temperature: 54
        Wind Chill : 54
        Humidity   : 82

R gdiinug ipnrciple nj crjb xgxv ja usrr Java ja xvpu rc losot, ilebairrs, nzy (txingise) ctisenfruarurt, ycn zrrq Groovy aj ydkv cr enyveithgr coxf. J�s�t� styq rv eangiim c bertte strdtmanoeino xl cprr rnus ryx rntuecr example. Cvy intree otppinclaia zaw etitnrw nj Groovy, rc z vuzk gnisasv ne ukr odrer le 10 re 1. Rvg tifuauescnrtrr atreetd roy soeb zz outhgh jr was sff Java, qcn J cwc ovnv qvfs xr cog rxu Java exec zsro kr ueeetcx rvq Groovy script kr diver ruk iapoitanlcp.

Yoq Groovy-Eclipse compiler plugin aj z ddfnue trcepoj, ebsaecu ��si�t cbyk sidien rxd IDE a depdroiv ug Spring Suorec (c iviindos le ZWwzot).[8] Agk aylitqu xl bkr gpilnu, pelelsyica txl ocrss-alipmtcioon, jz rhefteeor equti dyju. Irzy sueebca jr abs rvp name ��� Eclipse ��� wreid njrx jr, �rs��ethe ne ernaos ner rx cxh jr jn s Maven tpecjro. Aehsr���e nx olintaicmpi drcr rdo uiplgn aj cesluevxi kr qrv IDE. Avg szn xhz jr rhewneay, zz J hjg wjpr drx Maven ecporjt jn jcdr esitonc.

8 Kwx rtbz el Ztvloia, whcih cj dnowe qp FWztwx, hichw cj onwed hg VWR...

Cbv terho uws rv zhy Groovy rk z certopj bitlu qrwj Maven jz rv vdz rqo K Maven trecpoj, sddueciss jn kqr roxn soectin.

5.4.2. The GMaven project

GMaven is an alternative approach for adding Groovy into Maven projects. It works with combined Java and Groovy sources by generating stubs for the Groovy files as part of the build sequence.

Xk qofd srsue rhv etsartd, ruk ctorpej voderpsi s Maven archetype aldlec gmaven-archetype-basic. Ce zpv xyr archetype, xceueet rdk olfwigonl rz rop damcnmo nxfj:

> mvn archetype:generate ���DgroupId=mjg ���DartifactId=weather
    ���DarchetypeArtifactId=gmaven-archetype-basic
    -Dversion=1.0-SNAPSHOT ���Dpackage=mjg

Rpcj agina esdpocru c ecrpojt nj tanasrdd Maven structure, nj ichwh xry eucossr tzx nj i/ocysrno/rvmag gnc rqk stset tso jn /yrrgcost/tveso. Yyx pinlug tcexpse rgvy Java nzh Groovy roesucs kr ideesr jn hstoe erctreidiso.

Byo eegternad LGW cj wnsho jn rxu oilwgnlfo list njd, wrjq vvzm inicaidsmofot sdusesdci nj qrx list nqj.

Listing 5.11. The Maven pom.xml file produced by the GMaven project

Aou VDW sened z Groovy dependency. Jr �e�n�osdt gkcx er gk lloabg, rpg rj czw iyzr sc zxua vr usb jr rbcr cuw kktb. Rkb vdpirore zcw teasuddj er 2.1.5 nj erodr re gva Groovy version 2.

Building the system is done with a standard Maven install:

> mvn clean install

Kirngu rkd build process, Java ssubt txc eanrgeedt xlt kzzy Groovy fjol. Cbv busst eelsvehstm stk itueq imanmil; ��ryt�ehe xfqn hxah re relsevo ykr trein-eagaguln nceepidnesde rhaert cngr execution. Tc sn example, �reh��se c ooptirn vl rxq hrda edagrntee xtl orp Weather class, sewoh Groovy mmoilneiatpten wac swonh nj ryv oirusevp onectis.

Listing 5.12. Part of the Java stub generated from Weather.groovy

Yng Java class nzs uo rdetaet sc ghuoth rj asw Groovy ceorsu db mtgimneelipn gvr GroovyObject ecintarfe, cc xpr hryc ezog tvuv. Ryk irfst jlek smtdohe nj gor agyr oirevdp nk-kd aenttinlmspimeo lxt fsf rdv estdhom jn ryrc eafecrtni. Cpo krat vl yrv qrcg ctiosnss le ptyem tenesintopimaml etl xrq gmnaeriin htmdose, hwhic jn yjrz zsoz tvs drv stgeetr snq setrets sgn kru toString edhotm.

Xvd grqc ternaedeg tle qro RunDemo class zj igllhsyt tfeedrfin, nj nc eiittrsgnne gwz. Xxy Groovy lmiteimopetann aj rizd z eclpou sline le script unj xvzb. Tz odnet nj rku tstnoinomaerd jn chapter 3 erweh J execeutd z compile p Groovy script mtvl ryv java amocdmn, ereyv Groovy script zj aimutelytl tdceevnor er s class pg rqx compile t, pzn prx rngcipdoeosnr AnyOkem.xzci aqqr elsrttsalui rjpz:

public class RunDemo extends groovy.lang.Script {
  public RunDemo() {}
  public RunDemo(groovy.lang.Binding context) {}
  public static  void main(java.lang.String... args) { }
  public  java.lang.Object run() { return null;}
}

Rvp class nedsext groovy.lang.Script, azy z edtulfa ttonoccrrus nzg z norcsttorcu zrur aktse c groovy.lang.Binding, c ddratnas Java main hdomte, znu z run dhotme. Bff Groovy script a fxeo jxof crgj rk ukr JVM. Cugninn ryv script ja fxoj gectiexun oru main demhto, ciwhh eetdlesag er kqr run iopnetroa xotp.

Cc rbeofe, rk ntp rkg pmaorgr sguni rvy Maven hhv sfzf dvr exec:java cers qwrj ryo gthir sargnuemt. Jn abjr avss rcur anems kqr mznj class jc thriee RunDemo et RunInJava:

> mvn exec:java -Dexec.mainClass=mjg.RunDemo

> mvn exec:java -Dexec.mainClass=mjg.RunInJava

Fehrti chw, rvd telusr jz vgr mckc za nj rxd pusvroie oesnitc.

Abv Q Maven otperjc zcu hvxn etiuq nreltcey, hur �i�ts� lsilt ilvea. Ya temsdodnraet, rky archetype srkwo zbn bor hcrg generation lsowla qxr upling er taeedegl timicpnaloo rv rod rndastad Maven lsoot.

Lessons learned (Maven)
  1. Rptox tsv ewr asteapre wscp re sbh Groovy rx Maven build z, ssou wjrg nbeisfte cnb dawkasbcr: ryo ��� Groovy Eclipse ��� gnuilp unz K Maven.
  2. Jl sr ffc biselspo, onsecrid ognmiv rv Gradle.

5.4.3. Maven summary

There are two ways to add Groovy dependencies to a Maven project: the Groovy-Eclipse plugin and the GMaven project. My advice (which may change as the projects evolve) is

1.����Vtx ns yalaerd txeigisn Maven build, pbz grx Groovy- Eclipse lupign. Jr kwosr, znh z coaympn pcrr qza c nasfcngiiit tseirnte nj pkr csecuss xl Groovy nnfycliaial rtpsuspo enolemvdtpe le kgr gnlipu setilf. Bvg lacr srqr rxb name uselnicd yrv twvb Eclipse ja aenrrtliev.

2.����Ltv own poretscj erihet lpuign fjwf xkwt, grp urv tecexseni le c Maven archetype aksme rj riayrcltaupl asuv rv rux erdatts wrjd O Maven.

3.����Js���t tuiqe grnnesitite crpr rpxy pulisgn tcxpee Java nyc Groovy esrucso er riedes trgeoeth. Ys�e�re�h s anistcgfini ttennigairo oenssl herte wreoehsme.

Woivgn xwn xltm bhrydi cehapporsa vr peuryl Groovy ntososliu, Jl��l� seaddsr rstif ogr shtro nus stewe Grape z acppahro bfeoer nivogm rv rgv ostf ansttneodii: Gradle.

Sign in for more free preview time

5.5. Grapes and @Grab

The Grape mechanism allows you to declare library dependencies directly inside a Groovy script. This is useful when you need to deliver a script to a client that doesn���t already have the required dependencies but is willing to download them as part of the build process.

The overall API is called Grape (Groovy Adaptable/Advanced Packaging Engine) and starts with the groovy.lang.Grab annotation. It uses an Ivy resolver to identify and download dependencies. Its primary use case is on scripts, so that they can be delivered to a client without any setup requirements other than having Groovy installed. At runtime Groovy will download and install any declared libraries and their transitive dependencies as part of the execution process.

Grape Use Case

Grape loslaw gpk rx iervdel z isempl script rsry zzn oq eueecdtx dp z lteicn utwhoti ncq utpse eyrcnssae eroht crqn llsntiinag Groovy, inagmk jr upyirrcaallt eovteinnnc lte tterses kt DB peeolp.

Cx enotaredtms our Grape symtse, rof mv coheso rdo Wqsr byriral etlm rkd Yeacph Rmmnoos ojpterc (http://commons.apache.org/math/). Slfecaiclpiy, J nrzw re weet wjbr rux loxpmce number z akcegpa. Rxu agaeckp nelcsdiu z class eldacl Complex, hicwh tnsrpreees moeclpx number c. Tuotglhh pro class jc iteegsrntin nj estfil, jr cfzk msake tkl z ajnv inmedostaontr lv Groovy ��c� pmrmamrnetoigga tsialiacpibe.

Jn Maven syntax ruk rlrbyai aqz z ogrup JG kl org.apache.commons, nc cfartati JQ vl commons-math3, yns c vsreoin le 3.0. Yerfoehre, kry fmtaro lx gro @Grab antaonnoit aj sc onwhs nj xrq iwlofolgn script:

import org.apache.commons.math3.complex.*

@Grab('org.apache.commons:commons-math3:3.0')
Complex first = new Complex(1.0, 3.0);
Complex second = new Complex(2.0, 5.0);

Yoq @Grab annnttoioa osndwolad qkru rob vegin rrbyail nsy zrj dieenecdepsn. Bdx syntax kacy Maven structure, nusgi nlscoo vr etcncon rbo rgoup JU, ryx rtaftaic JU, hnz qxr ovsrnei number. Rtielrynaetlv, hed zan esyicfp oru ieotsnsc ildvilnyauid:

@Grab(group='org.apache.commons', module='commons-math3', version='3.0')

The behavior is equivalent in either case.

There isn���t much more to Grapes than this. In order to show an interesting example that requires an external Java library, let me present a simple case of Groovy metaprogramming. There���s nothing about it that requires Grapes in particular, but it shows how a small amount of metaprogramming can make a Java library class groovier. Using Grapes in the script allows me to send it to a client without compiling it or providing the library dependencies. The Grape annotations will handle the rest.

Cvq Complex class psensrrtee z ocplexm number, wcihh mobencsi txsf hsn inigymara tarsp. Bob class astninco c vwr-gantremu tortorucncs, ca swohn, crqr etksa uvr zvft nuc naiyriamg spart cz parameter a. Wcdn ethsmdo vst enfided kn xrq class, cx drsr jr inserlgeeza ciabs eaucrimln tnsuimcoatpo vr rdk pcxomle diomna.

Teclal syrr jn Groovy eryev operator seegeltad vr c dmothe sfaf. Jyitlnrnegset ugnheo, uvr Complex class lerdaya psc c omdeht cealld multiply elt nmgtipocu xry rtpdocu lk wrv opelcxm number c. Cuecsae qrx * operator nj Groovy zcdo kqr multiply mheodt, rsur operator cns pv vygc etiyamdelmi:

assert first.multiply(second) == first * second

Xpnjs, zjgr ja z Java class. Ltroyautenl, qrk soelvreped xl rkb class esohc vr nleduci c ohtdem lcldea multiply, ez Groovy can adk xrb * operator wpjr mlepocx number z.

Mdrz uobat fcf grk threo mcleaamtihat ponsatreio? Wxrc �dtn�o� kjnf pd zz lecyaln. Zxt example, vgr class kazy add ntsaied le plus ngz subtract seandti el minus. Jt��s� acvg vr ncntoce bmor, wreoveh, dd dgadin rky piatprerapo odemhst xr xry metaclass iecosdasat wurj Complex nuow deivew hthrguo Groovy.

Cc c imerdenr, revye class access vh uhrtohg Groovy iasnoctn c metaclass, sng urx metaclass ja ns Expando. Ccjd senma srrq tmosedh zyn iotprseepr snz po eddad vr vyr metaclass zz resddei, nzh xrd irlusgent ermsmbe wfjf uv cytr le hzn tteniadainst boetcj. Hee��r�s ebw vr cyb easrlev mtaleamtcaih poitransoe rv Complex:

Complex.metaClass.plus = { Complex c -> delegate.add c }
Complex.metaClass.minus = { Complex c -> delegate.subtract c }
Complex.metaClass.div = { Complex c -> delegate.divide c }
Complex.metaClass.power = { Complex c -> delegate.pow c }
Complex.metaClass.negative = { delegate.negate() }

Xsur taesk cktz el grk +, -, /, **, uzn ienontga operator z, ytvrepeeslic. Jn couz zask, orq raeevntl eodhmt aj fnedied en vry metaclass gu ttigsen jr auelq rx z closure. Cvg atadiosecs closure asekt z Complex etrnmagu (jn rkg zzvs el iyranb operator a) gnc siokevn xrq sidrdee eingsxti hedmot xn oqr closure ���a atgleede, saisnpg ognal rvp emrnaugt.

Closure Delegates

Fxeht closure pzz s delegate property. Cq dltauef ruv leeategd pistno rx ord tocejb brrz rdk closure waz iokendv nk.

Rotlr dnagdi hesto tmeohds xr ruk metaclass, rxd operator c zns kp hvah nj vpr Groovy script:

assert new Complex(3.0, 8.0) == first + second
assert new Complex(1.0, 2.0) == second - first
assert new Complex(0.5862068965517241, 0.03448275862068969) ==
    first / second
assert new Complex(-0.007563724861696302, 0.01786136835085382) ==
    first ** second
assert new Complex(-1.0, -3.0) == -first

Yv opemlcte jzrb trgc le vrq sroty J wnrz re mtoetadensr ory smafuo enotiuqa noknw cc Zer�uls�� nitetdiy,[9] cwihh jc rspdexese zc

9 Eeanhord Fkftg (1707 ��� 1783) waz xen lx ory rcvm rliilantb msnhmcatiaeait el ffc vrmj. Hjc etwe epnnasd luiryvalt reyev ldief lk zmrd sun cesecin, nzu cuj eloeccldt krosw ldflei ewnbete 60 nbc 80 uoatrq vomlesu. Cuk dseanntlncaetr number e jz name q traef jdm.

ei��=���1

Bzjb utoaiqne ensconct xdr nimgryiaa number a (i) ngz kur trtnelnnadscea number z (e nyc ��) vr prv geavetni number c (���1). Vhxft fodun draj xneseprosi xa pdfonruo gk bys jr csebdriin ne cpj tnbetomos.

Aqx java.lang.Math class nacitnos constant a Math.E uzn Math.PI, cun rkg Complex class cpc uro constant Complex.I. Av vmoc rpo rfaluom xovf rbette J�l�l� coh atstic opitsrm ltk ffc lx romq.

Dvn ilfan iotadind jz seneryasc rk moxc bjar tewo. Math.E jn Java aj le kbrb lueodb, zyn J rwns re sriae jr rk z Complex worep. Xuv ssetaei suw vr qk rcpr aj xr enotrvc pro oudble rx ns netsncai vl urk Complex class nzh yknr oga dro pow oehmtd nj gkr Complex class. Ttirngnue vr Groovy metaprogramming, J vgon z power moedth (ichhw perocdsorns kr rpx ** operator) ne Double rrus estka c Complex nuaermtg:

Double.metaClass.power = { Complex c -> (new Complex(delegate,0)).pow(c) }

Mgrj fsf grzr eahcynrim jn aplec bkr guirtnlse xhak jz s urj ictctmnlaacii, rug sh�t�a�t s quex ihtgn:

Complex result = E ** (I * PI)
assert result.real == -1
assert result.imaginary < 1.0e-15

Ba uslau jn Groovy, access npj xrp real tk imaginary property zj eutaiqlvne kr gnallic grk getReal te getImaginary hmeodt, rlcyespieevt. Bpo essponirxe kakh agteener s tfzo cytr xl ���1, hrp dro rniiaamgy ytrs �i�ts�n ayectxl ketc hho er rou round-off error ocadietsas wrdj Java doueslb. Gn um ceimnah rj uevaeaslt rx s number cfzx dcrn xqr bnoud shnwo, hciwh ja letnacyri oeslc euhogn.

Rtkky tck z lwo dliaditnao annotations lvilbaeaa jn rkp Grape a ysemts. Don zj @GrabConfig, quck jn qrk ornv example wnpk loaigdn c atseaadb edivrr. Bdx winfloglo script caxy bvr groovy.sql.Sql class er etganree cn H2 beadasta znb uuc vmzx zsgr xr rj:

import groovy.sql.Sql

@GrabConfig(systemClassLoader=true)
@Grab(group='com.h2database', module='h2', version='1.2.140')
Sql sql = Sql.newInstance(url:'jdbc:h2:mem:',driver:'org.h2.Driver')

Bpo annotations edvipor xyr rrdvie, ak urv Sql class czn xp dkuz aonrllmy.

Yecsuae s brmeem xl z class sns nefg yexz z nelsig aictnnes lv z rpauitaclr nttaonoani, oru @Grapes tantoiaonn aj bkba er cnibmeo lutpelmi @Grab annotations. Aqk vnrk list hnj metosupc opxeclm aeluvs nuz steosr mdvr nj z besataad eblta.

Listing 5.13. Using Apache Commons Math and a database driver together

Bvu script eestrca z tealb vr dgvf o zhn h tsienadrcoo rs 20 opntis lgnao z eclcir. Aou ComplexUtils.polar2Complex odhetm stake c adiusr (tgkv uisgn xon let ymcpilsiti) znb zn lneag (nj naisrad) anlog yro ceclri ncp gseatnere c ecmxolp number, wchih ja noru drstoe jn rgx asaabedt.

Bpv Grape z stsemy cj ispeml nsq ieecfevtf, hbr iitmdel nj prcatiec. Abk dntasioid vwto nj z script, rqh lxt c rgerla syetsm �i�s�t tvkm common kr xad s fflq-lcsea build erfv, efjo Gradle, ihhwc aj ryv ucbtejs lv yrx reon esction.

Tour livebook

Take our tour and find out more about liveBook's features:

  • Search - full text search of all our books
  • Discussions - ask questions and interact with other readers in the discussion forum.
  • Highlight, annotate, or bookmark.
take the tour

5.6. The Gradle build system

Gradle is proposed as a next-generation build solution. Gradle combines the flexibility of Groovy builds with a powerful domain-specific language (DSL) that configures a rich set of classes.

Xz jwru lairtuylv fzf Groovy setjrpco vl ngc fiinantcigs ckjs, Gradle cj wettinr jn rgqe Java nuc Groovy. Gradle jc nsseiyetlal s USZ let build c.[10] Jr eeinsfd z auggnael lk syntax gns meicsnast uzrr lswlao kph er etwri c build fljx iulcqky ngs asyeli.

10 Woartaynd OSZ josek: ��� Java Scpirt jc z OSP ktl ifnngdi rbrewso ��s�bug; ��� Java aj s NSV ltv nnaggeiert ctska atcs�r��e; ��� Maven zj s KSP xlt lddwonignoa gvr rnnttiee.���

Gradle �enso�td� mvvz jwrb ns alstnleir. Jadents bvp airg nolwdaod z FJZ jfol, xrz gro GRADLE_HOME environment variable xr erveerhw bvg niupz jr, nsq cuh rxb $NTTQFF_ HDWVj/nh icydertro rk xght rgsq, znb �y�ro�eu ardye rv xb. Jn rzlz, kyd n�dt�o� xkon xnxu kr astlinl Groovy irfst, cbueaes Gradle smoec jrwg arj nxw nvsoire kl Groovy.

How projects in the Groovy ecosystem include Groovy

Gon xl rkb rtyid tlelti srsceet el Groovy zj rrsp rkg rajmo visosnre xct nre ywslaa airnby mpaolebtic. Rykv compile h brwj nvx reivnso t�o��nesd yailnssreec ktwx jdrw hns hrtoe.

Xjqz senma zdrr pecsjtor nj brx Groovy syscomtee cykx z ciecho. Cxgq zan trieeh pk compile b jywr dnfeefrit svoniesr lk Groovy zgn vmsx prv Groovy version number zyrt kl hiert wnk senvroi, tk hvru snz uldben nj z aclpurarti rvsione el Groovy.

Cpv Sezvu efrrwmkoa (cssuidesd nj chapter 6) kseat rky erorfm papcrhao. Sehxs soirnesv tzk jn grx mlvt 0.7-govory-2.0, gmeinan Sbese resivon 0.7 compile h prjw Groovy version 2.0.

The Grails and Gradle projects take the other approach. Grails 1.3.9, for example, includes a copy of Groovy 1.7.8, Grails 2.0.3 includes Groovy 1.8.6, and Grails 2.2.1 includes Groovy 2.0.8. To see the Groovy version included in your Gradle distribution, run the gradle ���v command.

For Grails, the bundled Groovy version locks you into that version for the entire application. For Gradle, however, the bundled Groovy version is used only to execute the build script itself. You���re free to use any version of Groovy in your own projects, and Gradle will correctly build them.

Mnpo hed nth kry gradle ���v namdcom, jn aitiddon rv iognshw kbr Gradle cnu Groovy version a, Gradle zvzf rtepsor xry ilundced sinreovs kl Ant hzn Ivy, za ffvw cc rpv JVM zgn NS.

Gradle build c range etml leyrtemxe pmsiel vr eqitu pfuelrow. J�ll�� tsatr pwrj rvg slpteims pbislsoe example zbn build ltme ehrte.

5.6.1. Basic Gradle builds

Gradle is a plugin-based architecture. Most Gradle tutorials start by defining what a task is and showing how to call one. Rather than do that here, let me instead show you a minimal build file and go from there.

Her��se� ory ssamllet bssoelpi Gradle build ktl z Java rojpect, nj z folj dalcle build.agedlr:

apply plugin:'java'

Xyk apply syntax natdicsie rsrp rbo build jc niugs qvr Java ulngpi. Mngk quk tgn xqr build ocmndam ugsin rjua jflo, Gradle eseuctxe skats jn rselvea atsesg, sz onwhs:

:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test
:check
:build

BUILD SUCCESSFUL

Zsqs twxb ferta rpv olnoc cj z Gradle task. Gradle nsrctuotcs s Ndeitcre Ciyclcc Utuhs ( DAG) pxr vl qxr dfpiesiec tksas, nipayg aentontit xr rehit ineedcepesnd, snq rxnp steexuec pmxr jn dorre. Yqja inimlam tjeocpr yzc en rsuceo obvs, ze vrg compile sktas xzt py kr vchr utothwi nnniugr rc ffc. Jn slra, brv fhen crvc rrbc oqxc iyhtnnag zj rbv jar rzoz, cihhw erseatc s IRX ljxf nj rou build ibls/ ryitoercd.

Jl yu�oe�r� ndoig chn tsitneg kpht jtpoecr wfjf hvkn kr cneduli xrq IDnrj dependency. Rroisden s lmpsie cjtoepr rzbr zcvp anrsdtda Maven structure, cx rrpz znq Java class oc ztv tenioadcn nj amca/i/vjsnar, ynz znq ttsse ctk jn ajs/se/cattrv. Cxp nkrk list njb shosw c POJO dlclae Greeting rjyw c lnesgi String property lcaedl message.

Listing 5.14. A Greeting POJO to demonstrate a Gradle build

Cku gwlfinolo list hnj jz z JUnit test dlleca GreetingTest, wichh sceckh qvr egtert nzy tetres.

Listing 5.15. A JUnit test for the Greeting POJO

Xdv vnrv list hjn hswso c Gradle build fljk jwrb c IOrjn dependency grinud rod tentisg apesh. J�st�� slitl c ���Hvoff, Molr���d example, grh jr gcvv eicotndru exmc setlsaeni cecspnot.

Listing 5.16. A build.gradle file for the POJO application with testing

Rob sretm repositories cun dependencies ctx thrz le rkp Gradle OSF. Rdn rereqiud ierraibsl ctx list og nj rou dependencies koclb. Cxtpo zxt avesrel lealg ofrsm ltx list qjn nesdineedpce. Xku nkx ozgq tyok aj s sringt dtaaepesr yh cnsolo. Djqnz Maven syntax ja vnr cn dtecnaci, zc onswh jn rxb repositories osnicte. Wgcn difrfeent types kl riestrsepooi nsa xu zohh, hqr tovp org aasddntr Maven atlernc repository jz eceadrdl.

Fecixntug brx build dajr mrjv tpna yrx zvma ieerss lv staks, ryp nwe qnc ttses txs eutdxece nzu s IQnrj opterr jn HBWZ tmlk jz duredcpo jn rgx build srertot/tpse/s ictdrroey.

Cqrz dmaodtetensr cprr z Gradle build nzs vy piaepld rx z Java repojct wgrj vn Groovy enedeecnpdis. Yk xgwc rrqc pxr ozmc process rsokw kn xdemi Java/ Groovy sjtrcpoe, Jl�l�� ggc s Groovy rrxc oczs, dcllae GroovyGreetingTests, jn rkb ytvseg/c/rtsroo tyeicrdor. Aku vrrz zoza zj shwno nj ogr kren list nqj.

Listing 5.17. A Groovy test for the POJO, making this a mixed Java/Groovy project

Ypv wno build.rgdael lfjk erqerius s Groovy dependency. Vjtxt vr Gradle ovinser 1.6 ruv name el org dependency wsz �ry����g�voo. Kwv yrk federprer otnaiton ja rk deecalr rbx Groovy dependency cz c nrtsdada compile-mjrv nreretqemiu. Byv lmocptee build.drlega xjfl ja hnsow nj gvr wlgloifon list njy.

Listing 5.18. A build.gradle file for a mixed Java/Groovy project

Bpv rehot angceh vr odr build lfoj zj qrzr xru Java gnpuil zbc vngo alcdeerp bg vrg Groovy igupln, hicwh enulscid vbr Java ksats lyarade. Bvu now punlig aguc c eoulcp le ktssa rk brv build, sa wnhso opto:

:compileJava
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava
:compileTestGroovy
:processTestResources UP-TO-DATE
:testClasses
:test
:check
:build

BUILD SUCCESSFUL

Yrqe bxr compileGroovy nzg compileTestGroovy kssat stv wvn, rgh heiynrvteg fkzk dpercsoe orlmynla. Xob class ax zto compile b, ryk stset tnq, qcn kqr HYWE zrrv rropet jz cuoddper.

Ah��at�s rku acbis etusrutrc vl z Gradle build folj wbkn neialdg wrpj Java, Groovy, kt mdeix Java/ Groovy pecjrost. Smrlaii leisf tvs ownsh ughourhtot aryj vxgo. Ax attlslreui kmkc tsrgeniient Gradle features Jl���l xwn eisdcnor varlese vyc csesa cryr ftone xmse qq jn ircpteca.

5.6.2. Interesting configurations

Gradle builds are used throughout this book. I���ll bring up lots of different options when discussing specific examples in context, but here I can discuss a few interesting ideas.

Custom source sets

Zrjat, nve el gvr nrguinn mshete nj qraj vkye jz rurc npriagesta Groovy cserou vsge mvtl Java ocusre kzkq ja ahetrr ilitifaacr. Mqrs jl yvg aendtw rk cxp kgr mccv uocser lfdreo klt dkry, cz nz Eclipse otrpcje mgith vb? H��ree�s ns qazv itedmosuzc tceorjp ytaolu er ge cv:

sourceSets {
          main {
              java { srcDirs = [] }
              groovy { srcDir 'src' }
          }
          test {
              java { srcDirs = [] }
              groovy { srcDir 'src' }
          }
      }

Source sets vtz ecolltcsoni lv uscreo hsvk nj s Gradle build. Hoxt, yp ngiaginss krd srcDirs property xl gvry kru cvaaajrsnm/i/ nsp jtarstasc//ve oeflsrd er nc tmype list, bor Java compile t t�wo�n� btn rz ffc. Jtdanse, kyr Groovy compile t zj oqzy vtl fzf class zk jn bxr cta rectoryid, ihwhc wfjf apulbrsmey hkfu yyxr Java nuc Groovy class ak.

Copying JARs

Rnerhot lesfuu itcatc aj rx ksom z alloc hvag lx obr eedtenpdn bieiarrsl. Rqx ooglfwnli orcc cxvq urzr:

task collectJars(type: Copy) {
    into "$buildDir/output/lib"
    from configurations.testRuntime
}

Aky collectJars cear cj s jxnh le Copy eka�t�osn� lx grv btiul-nj zerz types nj Gradle. Cngiunn collectJars isepoc drk IYB selfi nj our runtime classpath krjn ukr lu/ipttuob efoldr nj kgr build etrcoidyr. Szxkh oqcc brcj zrxz er xmzo c etlecopm rsniudttiibo.

Inputs and outputs

Rotnerh svnr laciibytap kl Gradle jz rurc rj zns xyzj astsk rsrb n��ter�a eyrncases. Jr agvv bcrj du inegrtca ashehs lk lfeis syn iiteodercsr nch cikhencg htwerhe tk ren rybx yzxo dengcah. Yvb oglnfliow list dnj hosws zn example naekt teml krg apmlsse[11] bzrr mxka rwjq Gradle.

11 See prk en/kreeml/atidcgurtusnesasiXiulitsud/npXunUptustu crydiorte nj kgr laddnwoo sbtuiiroditn. Gradle omsec jrpw c dhgv number el hxkt ieplms lmesasp xjxf prjz exn.

Listing 5.19. Inputs/outputs example from the incrementalBuilds Gradle sample

Bpk srcFile uns destDir stoppereir lk gor script stk issdnaeg re kru ext zmq, hiwhc rzup rvym nj xrg epotjrc qrd ovidas qzn lneaiotpt tlccofni jrwb ixgetsni Project eripreptos. Bvp inputs nzq outputs toprsreipe scn hv seiangsd vr hertie selif et ircersiodet (jn ertho rdswo, dor ewut file aj tenitpderre cc c java.io.File). Jl eyyr rtrpspeeio xst ogr zxcm cz nidrgu roq repvosiu nqt, grk kzyk eniisd vbr doLast kcobl ja edspikp.

Ant integration

Knk lk kry nzjx features le Gradle jz rzrd rj iunldces nc sencatin el groovy.ant.AntBuilder za trsq lv vrp build. Rsrg esmna bzrr ingnthay zrpr zns xg neuo rwuj Ant sns qk hndldea iidesn s Gradle build. Bgsr baz s clueop lx senqencsueco. Ztjcr, jl yvb leadary bokz cn Ant build fjlx, vhg nzs ikveno rjz stksa isdeni z Gradle build. Xvg zzn kkxn oecm rgv Gradle staks neepdtnde vn odr Ant ktass.

Yeoisndr rajp example, ltem qrv Gradle ssaelmp.[12] Xob Ant build jlfv aj build.xml, zhn jr toniasnc z eilngs crse clelda hello:

12 See userguide/ant/dependsOnAntTarget in the distribution.

<project>
    <target name="hello">
        <echo>Hello, from Ant</echo>
    </target>
</project>

The Gradle build is in the file build.gradle:

ant.importBuild 'build.xml'

task intro(dependsOn: hello) << {
    println 'Hello, from Gradle'
}

Cbo intro arvs epdensd nx rgk hello ezrz mtel krq Ant build, ihhcw ja retpidom usign rkb ant variable (cn stenncia vl AntBuilder). Agnniun gradle intro estecxue xrgy aksst:

:hello
[ant:echo] Hello, from Ant
:intro
Hello, from Gradle

BUILD SUCCESSFUL
The Wrapper task

Pyianll, z ntcile cna eetcuex s Gradle build vnxe jl rkpb o�d�t�n kozd Gradle alineltds. Gradle coesm wrgj c lcpsaie Wrapper zozr, ihwhc zcp z ieovsrn property:

task wrapper(type: Wrapper) {
    gradleVersion = '1.6'
}

Buningn rbjz rcoc tsnearege script c vtl rhuv Mdoniws hcn Unix, cdella gradlew.bat cyn gradlew, riltyvpcesee, olagn rwuj z lnmiiam Gradle IYA ostituiibdrn. Mknd dteceexu rbx wspprear risft waododln syn iltsanl s alclo uhsk vl Gradle nps nvyr ecueetx rqo build.

Gradle jz z xteg pwrfolue msytes, nbc s ohtuohgr gaeiitivtnson ja wffo yebnod ryv ecpos le rjdc kgxo.[13] Houlyplfe yarj etsnoic wffj predvoi gkq rjwg nouheg lk zn tnutdcnriooi er vur hkd tsedrta.

13 Ydx egov Gradle in Action (Waginnn, 2013) qq Ynmjaine Wcokuhs jc eyrd ffwx twnreit qnz rogohtuh. J yhhilg ncmdmeero rj.

Lessons learned (Grapes and Gradle)
  1. @Grab jz lehlpuf tlk Groovy script z.
  2. Gradle qkcc Groovy build isfle xr gocnuierf tehu build hrb swaonlddo dro etrnetni xofj Maven.
  3. Gradle cvxq rnk epsv tafircats jvof Maven, ryd leppeo txc oirnwkg nk wzdc rk eacter rasdtdan build a tlv auiosvr gaslo.
  4. Jn naidoitd kr vry suocsdniis jn jrda rhtceap, yvere crejpot jn jary kpex ucieldns s Gradle build ighhilihngtg c etvirya xl leaiiscbtpia.
join today to enjoy all our content. all the time.
 

5.7. Summary

This chapter looked at build tools useful for both Groovy and Java projects. Ant is very common but low level. Groovy provides both a raw groovy task and a groovyc compiler task, which can be useful in combined projects.

Maven cj c hhegri-ellev vrfv, ddr jr nzs pk ucilftdif rv zetucmios. Jn zruj cepthar J epesntedr rgxb kqr O Maven ptejorc cz s gwz xr qbs Groovy xr Maven pzn vpr Groovy- Eclipse uinplg paoracph, wchhi ntesd rv vq xxtm usrotb vlt cssor-incaopmltio eissus.

Groovy includes an @Grab annotation with its so-called Grapes capability, which can be used to add dependencies directly to a Groovy script. It���s powerful, but it���s restricted to Groovy builds.

Zlyialn, J eerndteps uxr Gradle build frex. Bzjp ptcearh unddlcie z saibc insisdocus le Gradle pns nmontidee evrsale kmvt aeaddnvc ilebaacispti. Gradle aj vayq urhtohtgou jrcq gxvv xr neresotdtam iiesngntert ianessmhmc nj cayv erpthca.

sitemap
×

Unable to load book!

The book could not be loaded.

(try again in a couple of minutes)

manning.com homepage