Slide 1

Slide 1 text

Gianluca Costa Introduction to Apache Ivy Based on Ivy 2.5 Latest update: 2018-08-18

Slide 2

Slide 2 text

Foreword Elegance always matters, especially when creating vast and complex software architectures - and modularity is a core value of supple design Apache Ivy is a multifaceted tool dedicated to composing dependencies with a very high degree of exibility - not only for the Java ecosystem This work was inspired by my passion for build automation - for example, I created Aurora, my own build solution - as well as by valuable tech-themed coffee breaks with Marco Marani - especially on cache isolation, latest strategies and Maven compatibility 2

Slide 3

Slide 3 text

About this presentation We are now sailing on a brief tour of Ivy, trying to grasp its very essence - with no claim of completeness. Actually, Ivy is a huge eld full of details, so we can now describe just the tip of the iceberg; that should be enough to understand the overall picture and navigate its comprehensive documentation. Please keep in mind that there's often at least one way to alter the default behavior we are going to explore - so always consult the of cial reference for details! ^__^ 3

Slide 4

Slide 4 text

Section 1 Introduction

Slide 5

Slide 5 text

What is Ivy? Ivy is an open-source dependency manager It is written in Java and can run standalone, but it's even better when integrated in Apache Ant For Java projects, a basic scenario consists in: copying dependencies to a lib project directory - required by Java compiling, testing, ... publishing the project artifacts to a repository 5

Slide 6

Slide 6 text

Main features Extreme exibility: Ivy's most stunning aspect is probably its wide variety of hook points Declarative syntax for modules and settings Compatibility with Maven Transitive dependencies and con ict management Reports in different formats (HTML, graphs, ...) Ready for Continuous Integration and its artifacts High performances - if you con gure it well! 6

Slide 7

Slide 7 text

Section 2 Conceptual bricks

Slide 8

Slide 8 text

Simpli ed overview 8

Slide 9

Slide 9 text

Part 2.1 Modules

Slide 10

Slide 10 text

Module elements Module: self-contained, reusable software unit Descriptor: identi es the module and its artifacts Artifact: single le to be delivered as part of the module In Java, JAR archives are a standard Other compressed formats (such as zip) are anyway convenient Every module can include zero or more artifacts 10

Slide 11

Slide 11 text

Module descriptor Can have different formats: Ivy's ivy.xml le Maven's .pom le Even custom descriptors can be read, via dedicated Ivy plugins Attributes: uniquely identify the module, actually enabling Ivy to correctly resolve it 11

Slide 12

Slide 12 text

Ivy's descriptor attributes Organisation: identi es the producer - usually, via its inverted DNS name Module name: the name of the module itself Revision: unique identi er of a delivered module version - be it a release or just a CI publication Branch: the branch, in the version-control system, whose code generated the module (optional) Status: the stability of the module (optional) Publication: the publication timestamp - in yyyyMMddHHmmss format (optional) 12

Slide 13

Slide 13 text

Module status To describe the stability of a module, Ivy provides, by default, 3 categories: integration: the less stable - usually a nightly build (default) milestone: an un nished yet working module release: the most stable and tested publication type Additional statuses can be plugged into Ivy, if required 13

Slide 14

Slide 14 text

Module artifact attributes Name: lename, without extension Extension: lename extension (without dot); implies the format of the artifact - how it should be used. For example, jar, zip, png, jpg, txt ... Type: de nes the purpose of the artifact - why it should be used, e.g. binary and source code. For example, you could have 2 artifacts whose type is source code: the former as .jar, the latter as a .zip Packaging: implies post-resolution operations, such as extracting a directory from a zip artifact 14

Slide 15

Slide 15 text

Part 2.2 Con gurations and dependencies

Slide 16

Slide 16 text

Module con gurations Con guration = a way to use or construct a module In other terms, a con guration de nes the structure of the module in a speci c scenario: The dependencies required to build the module The artifacts published by the module A library might have different requirements according to whether it is in a CLI app or in a Java EE container If you do not declare any con guration, a public one named default is automatically created 16

Slide 17

Slide 17 text

Con guration attributes A module can declare one or more con gurations (also said conf's), each having these attributes: name - mandatory and unique within the module visibility: by default it is public; a private conf cannot be referenced by other modules description: the conf's description (optional) transitive: if true (the default), the conf becomes part of a chain of transitive dependencies deprecated: if the conf might be removed soon 17

Slide 18

Slide 18 text

Module dependencies A dependency is always declared as a reference to a module However, Ivy actually handles dependencies in terms of con guration mapping, which expresses how con gurations in the current module depend on public con gurations in the dependency Consequently, dependencies are not on artifacts, but on con gurations - which in turn provide a set of artifacts 18

Slide 19

Slide 19 text

Con guration mapping The notation used by Ivy is A->B - where: A is a con guration in the current module and is called master conf B is a con guration in the dependency module and is called dependency conf Both sides admit a *, meaning all con gurations. Both sides also admit a comma-separated list of confs: for example, A,B->C equates to A->C and B->C 19

Slide 20

Slide 20 text

Composite mappings In a mapping, you can explicitly declare multiple mappings separated by semicolons, for example: X->Y; A->A,B; Z->* X in this module depends on Y in the other A in this module depends on A and B in the other Z in this module depends on all confs of the other You can also make all con gurations require a speci c con guration in a dependency: * -> X 20

Slide 21

Slide 21 text

Special mappings *->@ means every conf maps only to the dependency conf having the same name - unlike *->*, which maps any to any % is only on the left side of -> and means all the other master con gurations not mapped until now. For example, in A->X; B->Y; %->Z, A gets X, B gets Y and all the other con gurations reference Z A->B(X): A references B, but if B is not available, reference X instead 21

Slide 22

Slide 22 text

Further mappings Con guration mappings can be even more sophisticated: please, refer to Ivy's documentation for more details: http://ant.apache.org/ivy/history/2.5.0- rc1/ivy le/dependency.html 22

Slide 23

Slide 23 text

Part 2.3 Versioning

Slide 24

Slide 24 text

Versions and dependencies In Ivy, the version of a module is denoted by the revision attribute in its descriptor. When declaring a dependency on another module, you must also state the version you require, which can be: a xed version - such as 1.5.2 a dynamic version - that is, a string that will be determined during the resolution phase, according to the modules available when running Ivy 24

Slide 25

Slide 25 text

Dynamic versioning latest.STATUS: selects the latest version of the module having the given STATUS - which can be one of the 3 default ones, or even a plugged one + notation: selects the latest version for just part of the revision. For example, if 2.1.3, 2.6.7, 2.6.8, 2.9 and 3.0 are available for a module, 2.6.+ will choose 2.6.8. Mathematical range: in the example above, both [2.0, 3.0[ and [2.0, 3.0) select the latest version that is both >=2.0 and <3.0 - that is, 2.9 25

Slide 26

Slide 26 text

Version con icts There are situations where Ivy nds multiple candidate versions of the same module - especially when navigating a complex dependency tree Ivy introduces con ict managers to lter such a set of con icting versions - most often, they select just one revision - somehow identi ed as the latest version You can also apply different con ict managers - even custom ones - to different modules Con ict managers try to be eager, evicting artifacts as soon as possible during the resolution process 26

Slide 27

Slide 27 text

Ivy's con ict managers latest-revision: selects the latest by revision - using a string comparison of revisions. (default) latest-time: selects the latest in time latest-compatible: selects the latest version also having a compatible set of dependencies all: just performs no ltering strict: stops the process with an error You can also de ne custom con ict managers, even via XML, especially ones based on a custom latest strategy 27

Slide 28

Slide 28 text

Latest version Ivy expects that we want the latest version in a range of situations - for example, in custom con ict managers To exactly de ne the latest version of a module, Ivy includes 3 default latest strategies - and even supports custom ones 28

Slide 29

Slide 29 text

Built-in latest strategies latest-revision: simple and ef cient, compares version components as expected in software development. In particular, Ivy's documentation mentions similarities with PHP's version_compare() latest-time: compares the revision timestamps. Conceptually simple, its drawback consists in the fact that retrieving such timestamps from remote sources can be quite a costly operation latest-lexico: compares revisions using Java's lexicographic order for strings 29

Slide 30

Slide 30 text

Circular dependencies The simplest circular dependency consists in a module A depending on a module B, which in turn depends on module A. Ivy has 3 different built-in policies to handle circular dependencies: warn: prints out a warning (default) ignore: just prints out a verbose-level message error: halts the resolution process 30

Slide 31

Slide 31 text

Part 2.4 Repositories and resolvers

Slide 32

Slide 32 text

Repositories Repository = distribution location providing modules. Also mentioned as repo Repositories can differ in a wide range of parameters: Location: local, remote Access protocol: le system, HTTPS, SSH, VFS, ... Descriptor format: Maven, Ivy, custom, ... Layout: how les are archived within the repo Dependency resolvers are Ivy's solution to the problem 32

Slide 33

Slide 33 text

Dependency resolvers Dependency resolver = pluggable Java class designed to access a repository in order to: Retrieve a module descriptor Retrieve the module's artifacts and, optionally, its transitive dependencies Publish module les - acting as a two-way channel From now on, we'll use resolver as shorthand for dependency resolver 33

Slide 34

Slide 34 text

Kinds of resolvers Resolvers can be divided into 2 main categories: Standard resolvers: provide concrete access to a repository. Examples: lesystem, url Composite resolvers: combine other resolvers in the context of a custom algorithm Examples: chain (which is extremely important), dual 34

Slide 35

Slide 35 text

Classes in Ivy con guration Resolvers are Java classes - however, it would not be practical to always mention them via their fully- quali ed class name (FQN) Instead, and as a general rule, Ivy provides XML tags - one per built-in resolver (we have just seen chain) Therefore, the attributes of each tag are mapped to properties of the related resolver instance We'll see that such an elegant mechanism is available for custom classes, too 35

Slide 36

Slide 36 text

Standard resolvers Standard resolvers encapsulate 2 distinct use cases: the access protocol to a repository the logic to locate descriptors and artifacts within it (the repository's layout) Both aspects are to be set up in order to successfully access any repository. Consequently, con guring a standard resolver can be thought of as a way to empirically describe a repository 36

Slide 37

Slide 37 text

Main standard resolvers bintray: Bintray repository, including JCenter ibiblio: ibiblio repository, including Maven Central url: very general way to access a repo via its URL lesystem: repository on the local lesystem ssh: repository accessible via SSH vfs: repo accessible via Apache Virtual File System sftp: repository hosted via SFTP jar: the whole repository is compressed as a JAR le 37

Slide 38

Slide 38 text

Locating les within a repo Now that we have seen that a standard resolver can access a repo, how does it locate a module's les (i.e., descriptor and artifacts)? Ivy's solution lies in patterns: Pattern = string denoting the path of a module's le. It includes special placeholders named pattern tokens. Every standard resolver has: patterns to locate the module descriptor (0 or more) patterns to locate artifacts (at least one) 38

Slide 39

Slide 39 text

Pattern tokens Pattern tokens are placeholders that are replaced by Ivy whenever it must locate a module's le - by injecting the Ivy coordinates of the requested le: Information set Pattern tokens Basic module info [organisation], [module], [revision] Additional info [branch], [orgPath], [conf] Artifact [artifact], [type], [ext], [originalname] 39

Slide 40

Slide 40 text

Pattern example This could be a reasonable pattern to organize the artifacts within a repo: [organisation]/[module]/[revision]/[artifact]- [revision].[ext] Such a pattern would resolve, for example, into: info.gianlucacosta/aurora/9.0/aurora-9.0.jar Of course, the pattern must re ect the actual internal structure of the repository - or les won't be found 40

Slide 41

Slide 41 text

Pattern tokens and variables Ivy supports variables - which are very similar to Ant properties - with a few differences such as the fact that Ivy variables can be overridden. Pattern tokens are similar to variables, but tokens are placeholders systematically replaced by Ivy with module and artifact coordinates, whereas variables exist on their own and usually have a longer lifespan - for example, they can be de ned in con guration les. It is interesting to note that a pattern can also include variables - in addition to pattern tokens, of course 41

Slide 42

Slide 42 text

Conditional groups in a pattern Conditional group: substring, in a pattern, delimited by parentheses and containing exactly one pattern token If the pattern token has a non-null, non-empty injected value, the token is replaced and the whole group appears as it is, without parentheses Otherwise, the whole group is omitted from the pattern A useful example is [artifact](-[revision]).[ext]: if revision is missing, the hyphen will be omitted as well 42

Slide 43

Slide 43 text

Pattern generality Patterns apply to a wide variety of contexts - not only repository access via resolvers. Wherever a pattern is requested, you can apply all the related features - such as pattern tokens and conditional groups. For example, we'll soon study the pattern attribute of the ivy:retrieve Ant task 43

Slide 44

Slide 44 text

Module descriptors and artifacts Technically speaking, module descriptors should not be classi ed as artifacts. However, you will often nd Ivy patterns for module descriptors that actually include the tokens dedicated to artifacts - especially [artifact], [type] and [ext], which work for module descriptors as well Similarly, Ant tasks such as artifacts in ivy:publish can also be used to locate the descriptor in the project dir 44

Slide 45

Slide 45 text

Composite resolvers Composite resolvers are not focused on directly retrieving les; instead, they orchestrate other resolvers (that can even be nested composite resolvers) according to a speci c algorithm. The most important composite resolvers are: Dual resolver: to decouple descriptor repo and artifact repo, especially when the latter is legacy Chain resolver: one of the most important Ivy resolvers, as it implements the concept of fallback strategy in the form of a chain of resolvers 45

Slide 46

Slide 46 text

Dual resolver Composite resolver that decouples module descriptor retrieval from artifact retrieval Consequently, module descriptors can reside in a repository and artifacts can reside in another - which is very useful when dealing with legacy artifacts It is con gured by providing 2 sub-retrievers: the former performs module descriptor resolution the latter performs artifact resolution 46

Slide 47

Slide 47 text

Chain resolver Composite resolver con gurable to sequentially look for modules within multiple repositories via the resolvers associated with it Actually applies the chain of responsibility pattern By default, it scans all of its repositories - useful if you are looking for the latest revision of a module - but you can also ne-tune it to return just the rst hit It can also be con gured as a dual chain: that is, the chain is queried once to fetch the descriptor and then again to separately fetch the artifacts 47

Slide 48

Slide 48 text

Retrieving the latest version Resolvers such as the chain resolver highlight the importance of the latest version concept for any Ivy dependency - both statically and dynamically versioned It is important to notice that your resolver might skip or limit the process of latest version selection - for example, we have seen that the chain resolver can return just the rst hit in lieu of querying its whole chain. If your latest strategy does not work as expected, please check both the con guration and the documentation of your resolvers 48

Slide 49

Slide 49 text

Forcing a resolver Every standard resolver has a force property that, when set to true, has a twofold effect: always looks for latest.integration, no matter what the requested revision actually is immediately return a matching dependency - even if used in a chain resolver not returning the rst hit This property can be especially useful on a resolver targeting one's local repository, so as to always get the latest version and skip queries on remote repos 49

Slide 50

Slide 50 text

Further details on resolvers Resolvers are a very exible area in Ivy's architecture: apart from the shared traits we have seen, every resolver has speci c properties To learn more details about resolvers, please refer to: http://ant.apache.org/ivy/history/2.5.0- rc1/settings/resolvers.html In particular, every resolver has a dedicated page, accessible from the navigation sidebar 50

Slide 51

Slide 51 text

Part 2.5 Combining repositories

Slide 52

Slide 52 text

Default repositories Ivy comes with sensible, exible default repository con guration, designed for enterprise developers working in a team You can keep this structure and con gure it - by setting the variables affecting it... ...but you can also design a brand-new set of repositories, tailored to your needs! 52

Slide 53

Slide 53 text

Default repositories - schema 53

Slide 54

Slide 54 text

Local repository The local repository is the developer's own repository If a dependency is found in it, the other repos are not accessed 54

Slide 55

Slide 55 text

Con guring local repository Directory: ivy.local.default.root= "${ivy.default.ivy.user.dir}/local" Descriptor pattern: ivy.local.default.ivy.pattern= "[organisation]/[module]/[revision]/[type]s/[artifact]. [ext]" Artifact pattern: ivy.local.default.artifact.pattern= "[organisation]/[module]/[revision]/[type]s/[artifact]. [ext]" 55

Slide 56

Slide 56 text

Shared repository The shared repository should be owned by the whole team It is accessed via lesystem, so it should reference a mount point - targeting, for example, network storage 56

Slide 57

Slide 57 text

Con guring shared repository Directory: ivy.shared.default.root= "${ivy.default.ivy.user.dir}/shared" Descriptor pattern: ivy.shared.default.ivy.pattern= "[organisation]/[module]/[revision]/[type]s/[artifact]. [ext]" Artifact pattern: ivy.shared.default.artifact.pattern= "[organisation]/[module]/[revision]/[type]s/[artifact]. [ext]" 57

Slide 58

Slide 58 text

Public repository The public repository is Maven Central, which is quite a common repository in the Java ecosystem. Of course, you might want to replace it with another repository, such as Bintray's JCenter, using the dedicated bintray resolver. 58

Slide 59

Slide 59 text

Part 2.6 Caching

Slide 60

Slide 60 text

Caching in Ivy Resolvers access repositories - but that might actually involve expensive operations - such as accessing a remote site Therefore, Ivy introduces caching - which is not to be mistaken for the local repository! Ivy has 2 levels of caching: resolution caching: internally used by Ivy and overwritten when a new resolution process starts repository caching: stores the actual repository les and related metainfo 60

Slide 61

Slide 61 text

Cache details Ivy has a built-in cache, by default referenced by all resolvers and which is the only cache that can perform resolution caching - to a resolutionCacheDir. It also performs repository caching to the repositoryCacheDir. You can de ne additional repository caches, each having a base directory (basedir). As already mentioned, such a directory must not be a repository - not even a local one! Every resolver points to one repository cache, which the resolver queries even before its own repository 61

Slide 62

Slide 62 text

Cache isolation Ivy's built-in caches are NOT thread-safe Again: Ivy's built-in caches are NOT thread-safe In the case of resolutionCacheDir: different Ivy processes running in parallel MUST point to different resolutionCacheDir directories In the case of repositoryCacheDir of the built-in cache, as well as for custom caches' basedir, you can enable concurrent access support by setting the cache's lockStrategy property to artifact-lock-nio 62

Slide 63

Slide 63 text

Change management By default, Ivy assumes that a module revision, once created, never changes - which makes caching simple! However, in practice, the assumption might be false: how to invalidate Ivy's cache in such cases? There are 2 distinct situations: Descriptor changes: patched metainfo, patched dependency declarations, ... Artifact changes: the most common example is the SNAPSHOT version in Maven and Gradle - designed to invalidate caching by de nition 63

Slide 64

Slide 64 text

Descriptor changes First of all, you should set the checkmodi ed property of your resolvers to true. This algorithm then applies: 1. If the last modi ed timestamp for the descriptor, as returned by the repository, is not more recent than the one in the cache, still use the cached version 2. Otherwise, update the cache - and use the new version 64

Slide 65

Slide 65 text

Artifact changes To support cache invalidation for artifacts, you must introduce the concept of changing dependency Set the changing property of the dependency to true, if you want to check just a speci c dependency Set the changingPattern and changingMatcher properties of your resolvers, if you want a generalized handling That does not end here - because Ivy applies a dedicated algorithm before invalidating a changing dependency 65

Slide 66

Slide 66 text

Changing dependencies The algorithm applied by Ivy is: 1. If the module metadata hasn't changed, still use the cache; this does not mean that you must always update it manually, as Ivy enriches the descriptor on publishing - e.g., setting the publication attribute - if missing - to the current build timestamp 2. If the module descriptor's publication attribute is not more recent than the cached one, still use the cache 3. Finally, update the cached artifacts, after checking each of them on a last-modi ed timestamp basis 66

Slide 67

Slide 67 text

Section 3 Ivy in practice

Slide 68

Slide 68 text

Part 3.1 Plugging Ivy into Ant

Slide 69

Slide 69 text

Ivy and Ant Ivy is a natural companion to Apache Ant In particular, it provides a set of Ant tasks that vastly simplify the process of: con guring Ivy retrieving dependencies publishing modules 69

Slide 70

Slide 70 text

Installing Ivy for Ant 1. Download the binary zip from Ivy's download page; for the most common scenarios, the zip without additional dependencies will suf ce 2. Copy Ivy's jar le to one of these directories: $HOME/.ant/lib - per-user installation $ANT_HOME/lib - global installation 3. Should you ever need to install the additional dependencies, please refer to Ivy's documentation 70

Slide 71

Slide 71 text

Ant project + Ivy The most common steps are: 1. Import the Ivy task library 2. Create a descriptor for the project - which now becomes a module. The default name is ivy.xml 3. Con gure Ivy, by reading its settings from an XML le - conventionally named ivysettings.xml 4. Retrieve the dependencies - that is, copy them to the lesystem - in our case, to a project subdirectory 5. Finally, mainly if the project is a library, publish it 71

Slide 72

Slide 72 text

Basic Ant build le with Ivy 72

Slide 73

Slide 73 text

Retrieving dependencies You need the ivy:retrieve Ant task, to which you should pass a pattern telling Ivy where the artifacts should be stored. The pattern usually points to a directory relative to the project's basedir - for example, lib 73

Slide 74

Slide 74 text

Retrieving and resolving Retrieving dependencies also automatically performs a few important actions: 1. Reading Ivy settings 2. Resolving dependencies - that is, ensuring they are in Ivy's cache system - which might also require accessing repositories via resolvers 74

Slide 75

Slide 75 text

Running Ant to get dependencies Given the example in the previous pages, and once the module descriptor is in place in the project directory, to retrieve all the dependencies one should just run: ant getDependencies to populate the lib dir and its subdirectories - where each subdirectory contains the dependencies of a speci c con guration 75

Slide 76

Slide 76 text

Part 3.2 Ivy descriptor

Slide 77

Slide 77 text

Introduction Ivy's module descriptor is a simple XML le declaratively stating several aspects of the module. By default, the descriptor is called ivy.xml and resides in the project directory - in this case making the ivy:info task super uous. We are going to see just the main points; for further details, please refer to the related documentation 77

Slide 78

Slide 78 text

Minimal descriptor Additional interesting information can be added: Other descriptor attributes, such as status and publication - but you can let Ivy add them Description, author details and license 78

Slide 79

Slide 79 text

Basic dependencies Basic dependency declaration is very similar to Maven - via the dependencies and dependency tag. As an example, to depend on a speci c version of our library: ... 79

Slide 80

Slide 80 text

Declaring con gurations In Ivy, you use the con gurations tag: you nest con guration tags within it its defaultconf attribute declares the con guration a dependency belongs to, if such dependency has no con guration explicitly declared its defaultconfmapping de nes the default con guration mapping, without bypassing defaultconf Actually, defaultconf and defaultconfmapping can equivalently belong to the dependencies tag 80

Slide 81

Slide 81 text

Dependencies & con gurations The dependency tag has a conf attribute, which is optional and whose value can be: a con guration name a con guration mapping - even a composite one As we have seen, Ivy always works in terms of con guration mappings when resolving dependencies 81

Slide 82

Slide 82 text

Dependency conf mappings 82

Slide 83

Slide 83 text

Con guration inheritance When a con guration extends one or more con gurations - via the extends attribute of the con guration tag - it automatically inherits all the dependency artifacts of the extended con gurations. For more details: http://ant.apache.org/ivy/history/2.5.0- rc1/ivy le/conf.html 83

Slide 84

Slide 84 text

Part 3.3 Publishing with Ivy

Slide 85

Slide 85 text

Resolvers as two-way channels We have used resolvers to resolve dependencies, fetching them from repositories However, Ivy expects that resolvers are two-way channels, actually able to write les into repositories Please, refer to the documentation of your speci c resolvers to ensure this assumption is true for all your resolvers 85

Slide 86

Slide 86 text

Publishing overview 1. Properly write ivy.xml - the module descriptor - declaring what your artifacts are 2. Con gure one resolver per target repository, using ivysettings.xml - although even the default con guration is ne (e.g.: the local resolver) 3. In Ant's build.xml: 1. call ivy:resolve - or a post-resolve task such as ivy:retrieve - at least once in the build 2. call the ivy:publish task for each repo, declaring the paths where the artifacts can be found 86

Slide 87

Slide 87 text

Declaring artifacts To declare artifacts, you need the publications block: It lies before the dependencies block It includes zero or more artifact tags If you omit publications, one module-related jar is assumed as artifact, whereas an empty publications tag means no artifacts, publish just the descriptor 87

Slide 88

Slide 88 text

Artifacts and con gurations Every artifact is always produced by one ore more con gurations: The artifact tag supports a conf attribute, accepting a comma-separated list of con gurations that produce it - making it available to other modules that depend on one of such con gurations The publications tag supports a defaultconf that is applied to any artifact tag missing the conf attribute. The default value is *, meaning all con gurations 88

Slide 89

Slide 89 text

The artifact tag In addition to conf, artifact supports attributes to set all of the properties we have already seen: name: defaults to the module's name type: defaults to jar ext: defaults to the value of type Additionally, it provides a url attribute to declare a fallback URL in case of missing artifact in the resolution process 89

Slide 90

Slide 90 text

Declaring the resolvers You must declare one or more resolver tags in your ivysettings.xml le, within the resolvers container tag. In the context of this example, we'll skip creating ivysettings.xml in the project directory, so that Ivy falls back to the default repositories - among which we'll be using local 90

Slide 91

Slide 91 text

Con guring Ant's ivy:publish In build.xml, the ivy:publish task has 3 paramount attributes: resolver: the name of the resolver used to publish. To publish to multiple repos, declare multiple ivy:publish overwrite: if set to true, overwrites existing les in the repo (default: false) publishivy: if set to true (the default), publishes the ivy.xml descriptor as well Its main subtag is artifacts - that we're going to see 91

Slide 92

Slide 92 text

The artifacts tag Ivy does not create artifacts - you must create them via your custom Ant build process Therefore, you must tell ivy:publish where the artifacts reside: to do so, you need one or more artifacts subtags - each for a possible artifact source (usually a subdir of a build or dist project directory) artifacts takes a pattern attribute, to match one or more artifact les in the project; pattern tokens - especially [name], [ext] and [type] - should be used. An example is in the next page 92

Slide 93

Slide 93 text

Artifact patterns - example The 2 artifacts tags state that artifacts can equivalently be taken from either dist/a or dist/b For each artifact, the patterns are applied in declaration order For each pattern, pattern tokens are replaced The rst pattern matching a le registers such le as the source of the current artifact 93

Slide 94

Slide 94 text

Artifact lename transforms Consider this line in Ant's build.xml for a project named TestLib - even if the module name in ivy.xml is test-lib: In this case, every published artifact declared in ivy.xml will be looked for in dist/TestLib.[ext]; for example: in ivy.xml will try to look for dist/TestLib.pom: it would be the source of the test-lib.pom artifact - which could later have even another lename in the repo 94

Slide 95

Slide 95 text

Artifacts and le names 95

Slide 96

Slide 96 text

The rst artifacts tag When you let Ivy publish the Ivy descriptor, it usually seems good to de ne the rst artifacts tag as follows: ... where dist is a directory, in the project tree, dedicated to receiving output artifacts. It can have any name. Ivy will store into this dir the enriched ivy.xml - having for example, a publication attribute stating the current build timestamp 96

Slide 97

Slide 97 text

Descriptor inheritance A module descriptor can inherit one or all sections from a published module descriptor. This can be achieved via the extends tag, under the info block in Ivy's descriptor. For example, to extend our sample module: 97

Slide 98

Slide 98 text

Documentation for ivy.xml ivy.xml lets you de ne several aspects of your module; for the full documentation please refer to: http://ant.apache.org/ivy/history/2.5.0-rc1/ivy le.html 98

Slide 99

Slide 99 text

Part 3.4 Ivy settings

Slide 100

Slide 100 text

Ivy con guration les Ivy is con gured via an XML le whose name is conventionally ivysettings.xml; it is an extremely vast topic - the very core of Ivy's exibility. The settings le contains Ivy's low-level, general con guration - which is therefore decoupled from the speci c module con guration - which in turn is provided by ivy.xml. Last but not least, Ivy can also be con gured by assigning values to speci c Ivy variables 100

Slide 101

Slide 101 text

Basic ivysettings.xml The include tag is great to include an existing, well- formed con guration le from the lesystem or a URL; every inclusion can also be marked as optional - causing no errors in case of missing le 101

Slide 102

Slide 102 text

Locating ivysettings.xml When calling Ivy from Ant: If you create ivysettings.xml in the project's build dir, it will be used in lieu of the default one If you use the ivy:con gure or ivy:settings Ant tasks, you can provide a le path or a URL - for example ${user.home}/ivysettings.xml - and will be used instead of the default one. It can have any lename Otherwise, Ivy's default settings le will be used 102

Slide 103

Slide 103 text

Referencing the default ivysettings.xml Whenever you employ a con guration le for Ivy, the default one is no more used. However, it has sensible defaults you might want to keep - such as the local, shared and public repositories. To reference the default con guration, you should employ the following include in your ivysettings.xml: 103

Slide 104

Slide 104 text

Con guring resolvers Resolvers can be de ned by adding sub-elements to the resolvers tag and by setting properties via tag attributes; for example: 104

Slide 105

Slide 105 text

Descriptor and artifact patterns To declare repository patterns, you need two subtags available when con guring all standard resolvers: ivy, with its pattern attribute, to declare 0 or more module descriptor patterns. This tag is vital when accessing a Maven repository, as it must be used to correctly locate the POM le of a module (see later) artifact, with its pattern attribute, to declare at least one artifact pattern 105

Slide 106

Slide 106 text

Using a resolver De ning a resolver is not enough: to use it during resolution, you have to to make it the default resolver*: Of course, if you want to use other resolvers as well - such as Ivy's default ones - you'll have to: 1. Add a chain to the con guration, containing both the new resolver and something else - such as one of the two default chains (default and main) 2. Set this new composite resolver as the default one 106

Slide 107

Slide 107 text

Resolver names and typedef Resolvers can be used as tags - because each built-in resolver has a dedicated tag - like chain, dual, lesystem, ibiblio, ... This mechanism is general: in ivysettings.xml, you can use the typedef tag to map a Java fully-quali ed class name (FQN) to a tag This is especially useful if you de ne custom resolvers, but it can be useful in other contexts - such as custom caches, custom con ict managers, custom latest strategies 107

Slide 108

Slide 108 text

Details on resolvers Resolvers are a universe, as they are one of Ivy's most valuable concepts. The general con guration details, as well as the per- resolver documentation, can be found at: http://ant.apache.org/ivy/history/2.5.0- rc1/settings/resolvers.html 108

Slide 109

Slide 109 text

Con guring the cache system A wise con guration for caching, shareable between projects as a conf fragment (via include tag) could be: resolutionCacheDir is project-private, so no con icts occur when different projects are built in parallel repositoryCacheDir is shared to save space, but with a NIO-based locking strategy enforced 109

Slide 110

Slide 110 text

Caching details The concepts already seen about caching in the previous sections actually map to the caches and cache tags. The related Ivy documentation can be found at: http://ant.apache.org/ivy/history/2.5.0- rc1/settings/caches.html 110

Slide 111

Slide 111 text

Further ideas Here are a few con guration ideas that you could explore: macrodef de nes a custom resolver via XML, by composing and customizing existing ones signers con gures signature generators parsers supports the creation of custom module descriptor parsers namespaces are an advanced feature, especially useful when dealing with legacy software and different repository conventions 111

Slide 112

Slide 112 text

Section 4 Maven compatibility

Slide 113

Slide 113 text

Is Ivy compatible with Maven? The answer is: de nitely! ^__^ In particular, Ivy can: retrieve modules from Maven Central with no con guration, via its public default repository access any other Maven repo - especially Maven local - just via minimal con guration extract a default set of con gurations from a POM - by converting the POM into an Ivy descriptor convert an Ivy descriptor to a POM, mapping con gurations to Maven scopes publish to a Maven repo, with no published ivy.xml 113

Slide 114

Slide 114 text

Module attributes equivalence Similarities in modules attributes can be summed up in the following table: Ivy concept Ivy attribute Maven POM attribute Organisation organisation groupId Module name module artifactId Revision revision version 114

Slide 115

Slide 115 text

De ning a Maven resolver To access, for example, the local Maven repo, you should add the following resolver to ivysettings.xml where ROOT should actually be replaced with: ${user.home}/.m2/repository/[organisation]/[module] /[revision] 115

Slide 116

Slide 116 text

The m2compatible attribute Resolvers such as lesystem and ibiblio support the m2compatible attribute; when it is set to true, the resolver behaves in a way similar to Maven: dots in [organisation] are converted into /, thus generating a longer path within the repository the resolver will look for POM descriptors transitive dependencies of POMs are enabled 116

Slide 117

Slide 117 text

Generated conf from Maven POM When depending on a module having a Maven POM, Ivy creates an ivy.xml in its repo cache having these confs: default: master artifact + runtime dependencies master: just the master artifact, with no transitive dependencies Maven scopes: compile, provided, runtime, test sources, javadoc - especially for IDE support optional, to get all the optional dependencies 117

Slide 118

Slide 118 text

Depending on Maven scopes For most Maven dependencies, you should depend on the default con guration, which provides: Maven's master artifact Its transitive runtime dependencies So, your conf mapping for a Maven dependency should be something like X->default, where X denotes one or more master con gurations; for simplicity, consider using also defaultconf and defaultconfmapping 118

Slide 119

Slide 119 text

Creating a POM le 1. Use Ant's ivy:makepom task in build.xml: 2. In ivy.xml, declare a dedicated artifact: ... ... 119

Slide 120

Slide 120 text

De ning Maven scopes To associate both dependencies and artifacts to Maven scopes, just create con gurations that are named like them: compile, provided, runtime and test. When creating the POM, Ivy will keep track of the mapping, assigning con guration dependencies to each scope. 120

Slide 121

Slide 121 text

Further POM customization Via attributes and subtags of ivy:makepom you can: De ne a mapping between Ivy con gurations and Maven scopes; the default mapping is by name, but you can manually perform a custom mapping between con gurations and scopes. Unmapped con guration will create, in the POM, unscoped optional dependencies Add further dependencies to the POM only Use a custom POM template, receiving injected Ivy variables 121

Slide 122

Slide 122 text

Locating the generated POM In build.xml, con gure ivy:publish by adding an artifacts subtag, using a pattern: ... The resolver attribute should point to a Maven repository resolver (having m2compatible=true) If you want to publish for Maven only, you can set publishivy to false 122

Slide 123

Slide 123 text

Section 5 Conclusion

Slide 124

Slide 124 text

Example project on GitHub To start playing with Ivy, you can explore the related GitHub project: https://github.com/giancosta86/IvyPlayground It consists of many subprojects featuring: a lot of explanatory comments what-if scenarios interesting cases studies, especially Maven compatibility 124

Slide 125

Slide 125 text

Final considerations We have come to the end of this introduction to Ivy: I hope you have found it a useful and structured guide to Ivy's vast universe of exibility! The best way to learn Ivy is now to practice a lot, always experimenting new ideas and keeping an eye on the online documentation. Thanks for your attention! ^__^ 125