When we started the Maven project, dependency injection was still developing. Spring was just starting out and the Avalon project at Apache was really the only IoC framework around. While the concept seems second-nature by 2010, in 2002, it wasn’t a primary focus of the initial efforts of the Maven community but it was something I felt had to be in place for the development of Maven 2. We knew we needed some sort of component framework, some standard mechanism to instantiate plugins and configure them based on a set of configuration points, and, at the time, Plexus filled the gap. Plexus was exactly what we needed because it evolved with the requirements of Maven, and I think that Plexus served us well for the past few years but it’s time to let go. I never felt compelled to switch until Guice 2.0. Guice has the capabilities and adaptability we require in Maven.
For all new development, we’ve decided to focus on Guice and build a compatibility layer for existing components. In this post, I’m going to discuss the various factors that went into the decision to move to Guice. All of Sonatype’s product are currently developed using Guice and the Guice/Plexus integration libraries that Stuart will describe in the articles that will follow over the next few weeks, and future work on Maven 3 will be based on Guice.
We ultimately went with Guice because it provided a system that could be configured and customized at runtime. It was very close to the model that Plexus was using, and we felt that it would be easy for us to build a compatibility layer between the two. The primary motiviation in this decision was our ability to write that compatibility layer atop whatever framework we selected that would allow for backward-compatibility. You see, it isn’t good enough in a community this large to just move to a new framework and expect everyone to just scramble to rewrite Maven plugins. We had to find a way to support existing plugins, and existing extensions. We had to find a way to work with all of the existing code that was coded to Plexus and adapt that to a new engine.
Guice is highly adaptable. With Guice we don’t need to configure all of our components ahead of time, we can instantiate them as needed and modify the “context” with a Guice/Plexus integration layer which Stuart will describe in the following articles. The answer to “why Guice?” is explained in the code that was required to write this compatibility layer. The only way we found to make this work was by using Guice. Other reasons included type safety, easy-to-read error messages, and OSGi support using peaberry. All of our development uses the JSR330 standard @Inject anotations. We’re using JSR330 instead of Guice-specific annotations to make sure that our work is more standard and portable going forward.
Focusing the Community
Aside from the technical reasons to move to Guice, there are reasons that involve the community. If our audacious goal is to provide world-class build and development infrastructure support, we need to remove unnecessary distractions from our environment. We just were not focused on Plexus, and issues would come up in Plexus that needed to be supported which distracted from the core effort. We’re not just *using* Guice. Because we are starting to rely on it, we appreciate the need to work closely with a project like Guice and contribute back to that community. Stuart is a committer, and we wanted to collaborate with others and use a framework used widely by others.
Maven’s goal was never to create a dependency injection framework, it was always focused on builds and the infrastructure that supports development. Not long ago, we were contemplating what it would take to improve Plexus, we looked at the effort required to document and support Plexus going forward, and it just didn’t make any sense for us to continue to apply precious time and effort to a problem that had already been solved by several others. It makes sense to focus the community, and moving to Guice will allow us to devote more of our own resources to supporting the central projects and products.
Making it Easier to Extend
When your project or production uses a standard tool, you increase the audience that can customize it. If the goal of Maven is to create a solid foundation of infrastructure for others to build upon, it only makes sense to adopt something more standard. Maven and products like Nexus should be judged by the number and variety of plugins that have been developed for them, and this is something that attract most new users to Maven (the abundance and variety of Maven plugins). Anything we can do to make it easier to extend these systems is the right thing to do for the “ecosystem” I described last week.
If you wanted to write a plugin for the initial version of Nexus two years ago, you would have had to know a lot about Plexus. There was nothing particularly wrong with Plexus, it had a well-defined interface and it served its purpose, but there wasn’t very much documentation, and requiring some knowledge of Plexus for plugin developers was reducing the size of potential developers. In the past year, we’ve made a course correction, and you can write a Nexus plugin without having to learn any dependency injection framework. What has made this transition possible is the flexibility of Guice.
Stuart’s going to dive into the technical details in the next five parts of this series. If you are a developer interested in the implementation of Plexus and Guice, you’ll find these posts to be a good starting point for learning about we’ve implemented this compatibility layer.