Home > Articles > Programming > Java

Dependency Management with Apache Ivy

Looking to get started with a simple dependency-management tool? The combination of Ant and Ivy is a solid proposition in this space, and this toolset may save you more than just time. Stephen B. Morris provides some clues.
Like this article? We recommend

Java Code Dependencies

Two popular options in the dependency management space are Maven and Ant/Ivy. Both toolsets have their merits, but in this article we'll look at the Ant/Ivy combination.

Ant is a build tool and Ivy is a dependency management tool. Maven, on the other hand, is both a build tool and a dependency manager. There are pros and cons to using two tools as opposed to one. With just one tool, you have a kind of one-stop shop. However, the combined tool may be a little harder to use than is the case for the individual tools.

With Ant and Ivy, each tool is dedicated to doing just one thing. This approach can make them a little easier to understand, particularly when things go wrong. Also, the Ant/Ivy combination is a good example of the old UNIX principle of doing one thing and doing it well: Ant is a solid build tool, and Ivy is likewise a reliable dependency manager.

Because of their close relationship, Ivy even comes with a set of pre-built Ant tasks to help you get started using Ivy. Before we get into the details of how to work with Ant/Ivy, let's look a little at the area of dependency management in general.

Rationale for Dependency Automation

How often have you struggled with Eclipse or some other IDE, trying to get rid of the compilation error markers in your Java files? This problem is often caused by missing (or incorrect) dependency errors. A little later in this article, we'll look at a concrete Eclipse example that illustrates the key role automatic dependency management can play in fixing these knotty issues. We'll also examine the workflow for using Internet repositories, such as Maven Central.

Managing code dependencies generally boils down to a simple choice: manual or automatic. If, like me, you prefer to exert a lot of control over your code dependencies, then the manual path is attractive, at least initially. However, a point tends to come when dependency management really needs to be automated.

When you think about it, complex dependency issues don't have a lot to do with design and coding, so it's natural to think about using a tool for this often tedious task.

As your code grows, it acquires what's called a tree of dependencies. Let's look at this next.

The Tree of Dependencies

Any Java project of reasonable complexity has a non-trivial set of dependencies consisting of JAR files with the internal resources needed to build, deploy, and run an application. Sounds simple, but these dependencies can get out of hand. Let's explore this with an example.

Adding a New Facility to Your Code

Let's say, for example, you read my earlier article "Java Data Validation Using Hibernate Validator," and you've decided to add a third-party validation mechanism to your application. Validation is often added late in a project, and very often programmers will opt to create their own bespoke solutions. But let's assume you decide to go with an open source solution.

One decent choice in this space is Hibernate Validator. To make this a little more concrete, let's assume that you already have an existing Ant build file. Adding Hibernate Validator then amounts to nothing more than installing Ivy and the addition of a single Ant target to fetch the dependencies. It's a similar story if you use Maven for dependency management; you just make a small addition to your metadata file pom.xml. Because I used Maven in the previous article, we can compare the two approaches.

Listing 1 illustrates the required Ivy setup for fetching the dependencies from the Maven Central Repository.

Listing 1—Adding an Ivy dependency.

<target name="maven2-namespace-deps-validator" depends="init-ivy" description="-->
install module with dependencies from maven2 repo using namespaces"> <ivy:install settingsRef="advanced.settings" organisation="hibernate"
module="hibernate-validator" revision="5.2.2.Final" from="${from.resolver}"
to="${to.resolver}" transitive="true"/> </target>

Don't worry about the details in Listing 1 for the moment. Listing 1 is basically like a little program that exists to fulfill our required dependency. The key part is the following section:

module="hibernate-validator" revision="5.2.2.Final" from="${from.resolver}" to="${to.resolver}" transitive="true"/>

This line specifies that we want to install a version of a given artifact; in this case, Hibernate Validator version 5.2.2.Final. Also, we want to use a specific source repository (from.resolver) and install the module in our destination repository (to.resolver). The two repositories are specified as Ant properties; in this case, respectively, Maven Central Repository (from) and a local file-based Ivy repository (to).

Transitive Dependencies

The potentially scary part in the above line is the setting for the transitive property. What are transitive dependencies? Well, transitive is a mathematical term that just means if module A has a dependency on module B, then both modules A and B will be downloaded. In other words, the transitive relationship is inferred by Ivy, and the appropriate artifacts are acquired automatically. Clearly, module B can also depend on C, and so on.

Once transitive dependencies are specified in this way, then all related artifacts will be downloaded for you. Setting transitive to true means that all our required dependencies will be downloaded. Sounds innocent, doesn't it? So what happens when we run this target? Well, we get a big bunch of files added to the local file-based repository, as illustrated in Figure 1.

Figure 1 Our new set of dependencies.

Figure 1 illustrates the outermost folder for each downloaded dependency. The longwinded point of this discussion is that the decision to add the required Hibernate Validator artifact is not without costs. What might those costs be?

For one thing, the deployed application now has to include these dependent modules. This requires disk space. At runtime, as the resources in the dependencies are used, there will be an associated memory requirement.

Depending on your deployment environment, some of these dependencies might already be available; for example, in a JEE scenario. However, if you're running a JSE application, you might well need all of the dependencies in Figure 1.

Clearly, automatic dependency management is a very powerful tool!

The sudden increase in dependencies that can result from adding an artifact such as Hibernate Validator can strike fear into the hearts of project team leaders. The resulting potentially complex web of dependencies is also, in a sense, an expression of how far open source development has come. So many useful utilities are available that you can simply add them to your code instead of developing them from scratch. The flipside is that such code may drag in other unwanted dependencies.

I recently read that something like 88% of all code (some 5 billion dollars' worth [1]) is now available as existing open source. In this context, the job of the programmer is often one of configuring existing tools and frameworks, rather than writing lots of new code.

It's important to be careful with the dependencies you add. Adding required artifacts to your Ant or Maven metadata files might be simple, but it also might result in a spaghetti of unnecessary dependencies. On the other hand, writing your own validation code also has issues. Skillful dependency management is a complex balancing act.

Dependency Bloat and Versioning

A less obvious burden in Figure 1 is the future need to manage the versioning of the dependencies. This issue is usually seen in codebases that have been around for a few years, where programmers use a given version of a library, such as log4j. Later, another programmer comes along and uses an updated version of log4j. Sadly, our second programmer doesn't update or delete the earlier code and its dependency.

The result is that we are now lumbered with two dependencies for the price of one. The underlying code may also be unnecessarily bloated, and without rules for handling this type of problem, the situation is only likely to get worse.

If you decide to add a new dependency, it's always a good habit to check whether any older dependencies can be retired. This might require some code changes if a programmer has written against a specific version of a library.

Ivy and Maven Port Use

Many organizations disallow the use of Internet code repositories, and with good reason. Maven Central passes back binary files to clients, which is not without risk. One way to ameliorate—but not eliminate—the risk of binary file download is by using digital signatures. Going back to Figure 1, if we double-click three times into the apache folder, this brings us to the actual JAR file and the digital signatures in Figure 2.

Figure 2 The artifact folder with the digital signatures.

Notice the signature files in Figure 2. This allows us to verify that the binary log4j JAR file matches the MD5 and SHA1 signature files. The presence of signature files doesn't guarantee that the files have not been tampered with, but it's one safeguard.

Running a Java Project After Dependency Acquisition

Let's create a simple Java project that requires the Hibernate Validator dependencies we downloaded earlier.

Listing 2 illustrates an example of a Hibernate Validator use case in a simple domain entity class. The example code is based on that at the Hibernate Validator site.

Listing 2—An entity domain class.

public class DomainClass {
        @NotNull
        private String manufacturer;

        @NotNull
        @Size(min = 2, max = 14)
        private String licensePlate;

        @Min(2)
        private int seatCount;

        public DomainClass(String manufacturer, String licensePlate, int seatCount) {
                this.manufacturer = manufacturer;
                this.licensePlate = licensePlate;
                this.seatCount = seatCount;
        }

        public static void main(String[] args) {
                DomainClass domainObject = new DomainClass(null, null, 10);
                
                ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
                Validator validator = factory.getValidator();

                Set<ConstraintViolation<DomainClass>> constraintViolations = validator.validate(domainObject);

                assertEquals(2, constraintViolations.size());
                assertEquals("may not be null", constraintViolations.iterator().next().getMessage());
        }
}

If we simply download the Hibernate Validator JAR file and add it to the Eclipse project build path, we'll run into a rather unfriendly exception such as the one in Listing 3.

Listing 3—Dependency-related exception.

Exception in thread "main" java.lang.NoClassDefFoundError: javax/validation/ParameterNameProvider
        at org.hibernate.validator.HibernateValidator.createGenericConfiguration(HibernateValidator.java:41)
        at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:269)
        at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:111)
        at validator.DomainClass.main(DomainClass.java:37)
Caused by: java.lang.ClassNotFoundException: javax.validation.ParameterNameProvider
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 4 more

Fixing this issue is a real pain if you opt for manual dependency management. This exception can be resolved by using Maven, or, as in our case, Apache Ivy. Once the dependencies have been downloaded as in Figure 1, we can then update the Eclipse build path and re-run the application. After applying the dependencies, we should see a successful application run, as illustrated in Listing 4.

Listing 4—A successful run.

Exception in thread "main" java.lang.AssertionError: expected:<1> but was:<2>
        at org.junit.Assert.fail(Assert.java:93)
        at org.junit.Assert.failNotEquals(Assert.java:647)
        at org.junit.Assert.assertEquals(Assert.java:128)
        at org.junit.Assert.assertEquals(Assert.java:472)
        at org.junit.Assert.assertEquals(Assert.java:456)
        at validator.DomainClass.main(DomainClass.java:42)

Programming Without Automatic Dependency Management

Though it can be very tiresome chasing down dependencies manually, this model is still used by many organizations. Unfortunately, the time you spend solving transitive dependency issues is time taken away from design and coding. By contrast, getting set up with Ivy has a once-only time cost, and thereafter dependency management is handled automatically.

Building a Simple Ivy Setup

The first step is to download Ivy. I won't duplicate the excellent content on the Ivy site. Getting up and running with Ivy isn't too difficult. A simple ivy.xml file such as the following is sufficient to download two artifacts (Commons lang and Commons cli, respectively) from Maven Central:

<ivy-module version="2.0">
    <info organisation="apache" module="hello-ivy"/>
    <dependencies>
        <dependency org="commons-lang" name="commons-lang" rev="2.0"/>
        <dependency org="commons-cli" name="commons-cli" rev="1.0"/>
    </dependencies>
</ivy-module>

A key required technique in Ivy.Maven dependency management is learning to use Maven Central. Let's have a look at this now.

Using the Maven Central Repository

Let's say you want to locate a given artifact, such as the Hibernate Validator, using Maven Central. The first step is to visit the Search Engine for the Central Repository. Next, type in the required artifact name, and you should see something like the excerpt in Figure 3.

Figure 3 Maven Central.

Click the generic link for 5.2.2.Final to the right of hibernate-validator-parent under "Latest Version." (The other links relate to OSGI artifacts—a somewhat more specialized area.) This brings us to another screen, illustrated in Figure 4.

Figure 4 Artifact details.

In Figure 4, notice the links under the heading "Dependency Information." This really useful part tells you what metadata to specify in order to acquire the artifact automatically. The metadata is supplied for POM (Maven), Ivy, etc. You select the Ivy setting, copy the metadata, and add it to your Ivy setup. In this case, you would copy the following line:

<dependency org="org.hibernate" name="hibernate-validator-parent" rev="5.2.2.Final" />

Just drop this dependency into your ivy.xml file, run ant, and the set of artifacts will be downloaded. It's that simple.

Other Dependency Management Tools

Maven and Ivy are just two among a range of popular dependency management tools. Gradle is another, referred to as a polyglot build tool. I haven't used Gradle, but it seems to be well suited to multiple-language environments.

Conclusion

Build tools and dependency management tools are closely related. Maven is an example of both. Ant and Ivy are separate tools—one for builds and the other for dependencies.

As codebases become larger and more complex, using a dependency manager is customary. In fact, it's usually advisable, as chasing down dependencies can become tiresome. This type of problem is seen when you add a new open source facility such as Hibernate Validator to your codebase. The required dependencies can be surprisingly large.

Provided that you're happy with the tree of dependencies, you can employ Ivy to fix some pretty knotty dependency problems, which sometimes are nearly too complex to fix by hand.

Getting set up with Ivy is straightforward, and if your organization allows Maven Central access, your migration should be relatively painless.

A key skill in using either Ivy or Maven is figuring out the metadata for your required dependencies. The Maven Central Repository provides easy tools for this task. Extracting a given dependency usually amounts to no more than copying a line of metadata into your local ivy.xml file.

It's important to note that the dependency management arena has a good few competitors. For example, Gradle is good for multi-language environments. It's not a one-horse race!

References

[1] Linux Format reports in the November 2015 issue that the total value of the Linux Foundation Collaborative Projects is estimated at approximately 5 billion dollars.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020