Skip to content
CMO & CTO
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

  • Digital Experience
    • Experience Strategy
    • Experience-Driven Commerce
    • Multi-Channel Experience
    • Personalization & Targeting
    • SEO & Performance
    • User Journey & Behavior
  • Marketing Technologies
    • Analytics & Measurement
    • Content Management Systems
    • Customer Data Platforms
    • Digital Asset Management
    • Marketing Automation
    • MarTech Stack & Strategy
    • Technology Buying & ROI
  • Software Engineering
    • Software Engineering
    • Software Architecture
    • General Software
    • Development Practices
    • Productivity & Workflow
    • Code
    • Engineering Management
    • Business of Software
    • Code
    • Digital Transformation
    • Systems Thinking
    • Technical Implementation
  • About
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

Dependency Management that Doesn’t Bite

Posted on March 21, 2007 By Luis Fernandez

Why do jar dependencies keep biting the hand that feeds them?

If you build Java apps for a living, you have met the broken classpath at 6 pm on a Friday. You drop a jar in a lib folder, Ant compiles, the app starts, then boom at runtime a missing class from yet another jar shows up. You chase that jar, then the next, then you ship a fat war with duplicates and mystery versions. It works on my machine becomes a lifestyle. There has to be a better way to say what we need and let the tool fetch it without drama.

I have the scars. You probably do too.

Enter Maven. Not as a silver bullet but as a boring friend who brings order. You write a pom.xml that declares groupId, artifactId, version, and Maven figures out transitive dependencies. You ask for Spring and it also gets the jars Spring needs. It uses a local cache in your home folder and a shared central repository. The big win is that the rules are written down so the build server can do the same thing you do.

It can also surprise you by pulling in the world if you are not specific.

My first rule is simple. Pin versions. Version ranges look fancy but they move under your feet. A minimal POM that stays put looks like this:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example.demo</groupId>
  <artifactId>catalog-service</artifactId>
  <version>1.0.0</version>

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>2.0.4</version>
    </dependency>
  </dependencies>
</project>

Pin versions. Future you will thank you.

Next rule. Control the tree. Transitive is helpful until a library drags a logging stack you do not want. Use exclusions to keep your house quiet and pick your logger or XML parser on purpose.

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate</artifactId>
  <version>3.2.2.ga</version>
  <exclusions>
    <exclusion>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
    </exclusion>
  </exclusions>
</dependency>

Say no early. The tree stays clean.

Many of us build behind a proxy or we cache jars in house. Maven plays nice with both. Set your proxy and mirrors in settings.xml. If you run Apache Archiva or a simple file share mirror, point Maven at it. Your builds speed up and keep working when the internet blinks or Central gets slow.

<settings>
  <proxies>
    <proxy>
      <id>corp-proxy</id>
      <active>true</active>
      <protocol>http</protocol>
      <host>proxy.company.local</host>
      <port>3128</port>
    </proxy>
  </proxies>

  <mirrors>
    <mirror>
      <id>internal</id>
      <name>Internal Mirror</name>
      <url>http://repo.company.local/maven2</url>
      <mirrorOf>central</mirrorOf>
    </mirror>
  </mirrors>
</settings>

Central is nice. Your build server behind the firewall is nicer.

Scopes are your friends. Use test for JUnit, provided for Servlet API when a container gives it to you, and runtime when you only need a jar at runtime. This keeps your compile classpath lean and your war files sane.

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>servlet-api</artifactId>
  <version>2.4</version>
  <scope>provided</scope>
</dependency>

Your war should not carry what the container already has.

When things feel weird, ask Maven what it thinks. The dependency plugin prints the tree and shows where a jar came from and which version won a conflict. The nearest one in the path wins, which is a simple rule once you see it.

mvn -q dependency:tree
mvn dependency:purge-local-repository
mvn -o package   # offline after you cache

Keep trees small and boring.

We all like tools that fade into the background. Maven can do that if we respect a few basics. Be explicit about versions. Exclude what you do not want. Use scopes to match reality. Point Maven at a local cache or mirror and make the build server use the same settings. Then your commit is not a surprise party for the next person who types mvn package.

Dependency management should feel boring and repeatable, not heroic.

Engineering Management Software Engineering

Post navigation

Previous post
Next post
  • Digital Experience (94)
    • Experience Strategy (19)
    • Experience-Driven Commerce (5)
    • Multi-Channel Experience (9)
    • Personalization & Targeting (21)
    • SEO & Performance (10)
  • Marketing Technologies (92)
    • Analytics & Measurement (14)
    • Content Management Systems (45)
    • Customer Data Platforms (4)
    • Digital Asset Management (8)
    • Marketing Automation (6)
    • MarTech Stack & Strategy (10)
    • Technology Buying & ROI (3)
  • Software Engineering (310)
    • Business of Software (20)
    • Code (30)
    • Development Practices (52)
    • Digital Transformation (21)
    • Engineering Management (25)
    • General Software (82)
    • Productivity & Workflow (30)
    • Software Architecture (85)
    • Technical Implementation (23)
  • 2025 (12)
  • 2024 (8)
  • 2023 (18)
  • 2022 (13)
  • 2021 (3)
  • 2020 (8)
  • 2019 (8)
  • 2018 (23)
  • 2017 (17)
  • 2016 (40)
  • 2015 (37)
  • 2014 (25)
  • 2013 (28)
  • 2012 (24)
  • 2011 (30)
  • 2010 (42)
  • 2009 (25)
  • 2008 (13)
  • 2007 (33)
  • 2006 (26)

Ab Testing Adobe Adobe Analytics Adobe Target AEM agile-methodologies Analytics architecture-patterns CDP CMS coding-practices content-marketing Content Supply Chain Conversion Optimization Core Web Vitals customer-education Customer Data Platform Customer Experience Customer Journey DAM Data Layer Data Unification documentation DXP Individualization java Martech metrics mobile-development Mobile First Multichannel Omnichannel Personalization product-strategy project-management Responsive Design Search Engine Optimization Segmentation seo spring Targeting Tracking user-experience User Journey web-development

©2025 CMO & CTO | WordPress Theme by SuperbThemes