$30 off During Our Annual Pro Sale. View Details »

Introduction to Apache Ivy

Introduction to Apache Ivy

Apache Ivy is a multifaceted tool dedicated to composing dependencies with a very high degree of flexibility - not only for the Java ecosystem.

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 field 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.

Gianluca Costa

August 18, 2018
Tweet

More Decks by Gianluca Costa

Other Decks in Programming

Transcript

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

    View Slide

  2. 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

    View Slide

  3. 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

    View Slide

  4. Section 1
    Introduction

    View Slide

  5. 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

    View Slide

  6. 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

    View Slide

  7. Section 2
    Conceptual bricks

    View Slide

  8. Simpli ed overview
    8

    View Slide

  9. Part 2.1
    Modules

    View Slide

  10. 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

    View Slide

  11. 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

    View Slide

  12. 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

    View Slide

  13. 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

    View Slide

  14. 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

    View Slide

  15. Part 2.2
    Con gurations and
    dependencies

    View Slide

  16. 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

    View Slide

  17. 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

    View Slide

  18. 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

    View Slide

  19. 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

    View Slide

  20. 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

    View Slide

  21. 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

    View Slide

  22. 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

    View Slide

  23. Part 2.3
    Versioning

    View Slide

  24. 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

    View Slide

  25. 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

    View Slide

  26. 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

    View Slide

  27. 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

    View Slide

  28. 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

    View Slide

  29. 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

    View Slide

  30. 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

    View Slide

  31. Part 2.4
    Repositories and resolvers

    View Slide

  32. 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

    View Slide

  33. 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

    View Slide

  34. 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

    View Slide

  35. 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

    View Slide

  36. 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

    View Slide

  37. 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

    View Slide

  38. 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

    View Slide

  39. 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

    View Slide

  40. 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

    View Slide

  41. 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

    View Slide

  42. 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

    View Slide

  43. 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

    View Slide

  44. 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

    View Slide

  45. 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

    View Slide

  46. 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

    View Slide

  47. 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

    View Slide

  48. 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

    View Slide

  49. 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

    View Slide

  50. 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

    View Slide

  51. Part 2.5
    Combining repositories

    View Slide

  52. 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

    View Slide

  53. Default repositories - schema
    53

    View Slide

  54. 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

    View Slide

  55. 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

    View Slide

  56. 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

    View Slide

  57. 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

    View Slide

  58. 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

    View Slide

  59. Part 2.6
    Caching

    View Slide

  60. 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

    View Slide

  61. 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

    View Slide

  62. 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

    View Slide

  63. 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

    View Slide

  64. 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

    View Slide

  65. 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

    View Slide

  66. 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

    View Slide

  67. Section 3
    Ivy in practice

    View Slide

  68. Part 3.1
    Plugging Ivy into Ant

    View Slide

  69. 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

    View Slide

  70. 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

    View Slide

  71. 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

    View Slide

  72. Basic Ant build le with Ivy
    xmlns:ivy="antlib:org.apache.ivy.ant">





    72

    View Slide

  73. 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


    pattern="lib/[conf]/[artifact](-[revision])(.[ext])" />

    73

    View Slide

  74. 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

    View Slide

  75. 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

    View Slide

  76. Part 3.2
    Ivy descriptor

    View Slide

  77. 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

    View Slide

  78. Minimal descriptor

    organisation="info.gianlucacosta"
    module="test-library"
    revision="1.5" />

    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

    View Slide

  79. 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:

    ...

    name="test-library"
    rev="1.5" />


    79

    View Slide

  80. 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

    View Slide

  81. 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

    View Slide

  82. Dependency conf mappings
    82

    View Slide

  83. 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

    View Slide

  84. Part 3.3
    Publishing with Ivy

    View Slide

  85. 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

    View Slide

  86. 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

    View Slide

  87. 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

    View Slide

  88. 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

    View Slide

  89. 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

    View Slide

  90. 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

    View Slide

  91. 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

    View Slide

  92. 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

    View Slide

  93. 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

    View Slide

  94. 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

    View Slide

  95. Artifacts and le names
    95

    View Slide

  96. 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

    View Slide

  97. 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:
    module="..." revision="..." />
    module="test-library"
    revision="1.5" />

    97

    View Slide

  98. 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

    View Slide

  99. Part 3.4
    Ivy settings

    View Slide

  100. 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

    View Slide

  101. 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

    View Slide

  102. 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

    View Slide

  103. 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

    View Slide

  104. 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:




    pattern="${user.home}/.m2/repository/..."/>


    104

    View Slide

  105. 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

    View Slide

  106. 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

    View Slide

  107. 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

    View Slide

  108. 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

    View Slide

  109. Con guring the cache system
    A wise con guration for caching, shareable between
    projects as a conf fragment (via include tag) could be:

    resolutionCacheDir="${basedir}/.ivy-cache"
    repositoryCacheDir="${user.home}/.ivy2/repo-cache"
    lockStrategy="artifact-lock-nio" />

    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

    View Slide

  110. 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

    View Slide

  111. 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

    View Slide

  112. Section 4
    Maven compatibility

    View Slide

  113. 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

    View Slide

  114. 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

    View Slide

  115. De ning a Maven resolver
    To access, for example, the local Maven repo, you
    should add the following resolver to ivysettings.xml

    m2compatible="true">




    where ROOT should actually be replaced with:
    ${user.home}/.m2/repository/[organisation]/[module]
    /[revision] 115

    View Slide

  116. 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

    View Slide

  117. 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

    View Slide

  118. 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

    View Slide

  119. Creating a POM le
    1. Use Ant's ivy:makepom task in build.xml:
    ivyfile="ivy.xml"
    pomfile="dist/${ant.project.name}.pom" />
    2. In ivy.xml, declare a dedicated artifact:

    ...

    ...

    119

    View Slide

  120. 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

    View Slide

  121. 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

    View Slide

  122. Locating the generated POM
    In build.xml, con gure ivy:publish by adding an
    artifacts subtag, using a pattern:
    publishivy="false">
    ...


    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

    View Slide

  123. Section 5
    Conclusion

    View Slide

  124. 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

    View Slide

  125. 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

    View Slide