DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • JGit Library Examples in Java
  • While Performing Dependency Selection, I Avoid the Loss Of Sleep From Node.js Libraries' Dangers
  • Understanding ldd: The Linux Dynamic Dependency Explorer
  • Why You Don’t Need That New JavaScript Library

Trending

  • How Can Developers Drive Innovation by Combining IoT and AI?
  • Understanding IEEE 802.11(Wi-Fi) Encryption and Authentication: Write Your Own Custom Packet Sniffer
  • Integration Isn’t a Task — It’s an Architectural Discipline
  • AI-Driven Root Cause Analysis in SRE: Enhancing Incident Resolution
  1. DZone
  2. Coding
  3. Frameworks
  4. Kill Your Dependencies: Java/Maven Edition

Kill Your Dependencies: Java/Maven Edition

Learn how to kill your dependencies in Java/Maven with these tips, like shooting for zero dependencies, and NOT including Spring.

By 
Sam Atkinson user avatar
Sam Atkinson
·
Feb. 23, 16 · Analysis
Likes (36)
Comment
Save
Tweet
Share
42.1K Views

Join the DZone community and get the full member experience.

Join For Free

I recently came across this excellent article on dependency management in Ruby.  It rightly states that the concerns are language agnostic and I really think it’s worth covering specifically for Java and Maven as so many people repeatedly get it wrong.

I’ve spent most of my career working in very large organisations with cross-cutting concerns.  Any given project will have a dependence on around 4 or so other systems, give or take.  For a variety of reasons (poor/no guidance, no architects who can code) this interdependence has been implemented in a myriad of ways, but with a surprising reliance on client libraries.  Whether this is a good or bad thing (it’s a bad thing) is for a whole other post, but I’ve had the pleasure of suffering first hand due to poor dependency management in client libraries.  In this post, I’m going to cover some important do’s and don’ts.  Whether you’re making a client library, a util library, or anything which someone else will be relying on, please follow these rules.  They will make you liked and loved by other teams.

Big open caveat up front; I’ve made a number of these mistakes myself earlier in my career.  I hope you can learn from my errors.

Make it Tiny: Aim for Zero Dependencies

The best client library is one that depends on nothing else.  This way the consumer faces no risk of clashing libraries and versions.  You should go to relatively extreme distances to achieve this.  

There are a bunch of helper libraries people have as go-to's - Guava and Apache Collections are two of the more common ones I see.  I know you may find them really useful and the idea of coding without them is crazy, but don’t do it. Every consumer of your library is going to have to bring in the entirety of that dependency into their code base just because you want a simple way to find the differences in a list.  This is really bad.  This gets worse when the consumer is operating on a newer version of the library than you and there are breaking API changes. They may be forced to downgrade and use and old version because you don’t keep your libraries up to date.

If you simply cannot live without certain functions from a dependency (but it’s still a minority of the library), copy the code out of the library and include it in your codebase.  It’s controversial as you will have to manually upgrade it if the dependency changes, but if it’s something stable then it probably won’t need to happen. Just make sure you change the package space, and maybe even the class name, so there are no clashes if the consumers use the same library.

For the Love of God Don’t Include Spring

This is one of the cases I’m very guilty of.  One of my first tasks as a junior dev was to create a client/server comms layer running over ActiveMQ.  I was deep into my Spring phase and every single library I created for other dev included Spring and mandated the use of Spring to use it.

I was a very junior developer.

Firstly, your library should in no way mandate or influence how the consumer wires up their application.  If they want to use Spring, Guice, or manually wire it then it’s dealers choice.  You are creating a library. Provide functions, don’t override the consumers choice.

Secondly, Spring causes dependency mismatch hell.  It has breaking changes between 2, 3 and 4, and differing behaviour on sub-point releases.  I’ve seen a project where they had to create a separate component (a Martin Fowler simplification) to handle a client library because they were unable to resolve the clashes between spring 2.5.6 and spring 3.0.1.  This is insane.

This also very clearly applies to other libraries than Spring, it just happens I have the most experience with Spring pain.  I refer you to point 1- aim for zero dependencies.

Use the Maven Dependency System: Do Not Use Fat Jars

One of the benefits of Maven is that a consumer can choose to exclude your dependencies.  If you’ve built your library well it hopefully won’t be needed, but you should always aim to give the consumer the most choice, whether that’s ignoring or overriding your dependencies.  If you choose to use a far jar (that is, your project has the jars and/or classes for all of the things you depend on) then you are forcing the client to use, and be stuck on, whatever you’ve packaged.

At my last role, a fairly important central team had done this.  They’d copied and pasted the code from Spring and Apache Collections and a bunch of other stuff into their Jar, and hadn’t changed the package space. This invariably leads to clashes and problems for all of the consumers, exacerbated by the fact that it was never updated and had libraries that were years out of date.  

All the major dependency management systems such as gradle are compatible with Maven. Use it properly.


Only depend on things you need

It's really easy to leave dependencies in that you don't need anymore.  It's hard to figure out if a dependency is still valid. Fortunately, there's a tool for that- The Maven Dependency Analyzer. If you stick this into your build it will log out to tell you exactly which dependencies you've got which you don't need, along with dependencies you need that you haven't explicitly got (and are liable to cause your system to break if your dependencies change).


Logging out isn't always enough though; throw in the Maven Enforcer Plugin on your build and if your dependencies are wrong then the build will fail.  Beautiful!

Dependency Library Spring Framework consumer

Opinions expressed by DZone contributors are their own.

Related

  • JGit Library Examples in Java
  • While Performing Dependency Selection, I Avoid the Loss Of Sleep From Node.js Libraries' Dangers
  • Understanding ldd: The Linux Dynamic Dependency Explorer
  • Why You Don’t Need That New JavaScript Library

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: