When we started the Maven project, dependency injection was still developing. Spring was just starting out, and the Avalon project at Apache was 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. I think 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 need 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 Sonatype's products are currently developed using Guice, and the Guice/Plexus integration libraries 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 it would be easy for us to build a compatibility layer between the two. The primary motivation in this decision was our ability to write that compatibility layer atop whatever framework we selected that would allow backward compatibility. You see, it isn't good enough in a community this large to move to a new framework and expect everyone to 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 the existing code 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 required to write this compatibility layer. The only way we found 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 annotations. We're using JSR330 instead of Guice-specific annotations to ensure that our work is more standard and portable going forward.
Apart 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 committee, and we wanted to collaborate with others and use a framework widely used 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 didn't make any sense for us to continue to apply precious time and effort to a problem already 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.
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 developed for them, and this is something that attracts 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 wrong with Plexus, it had a well-defined interface and served its purpose, but there wasn't much documentation. Having some knowledge of Plexus for plugin developers reduced the size of potential developers. In the past year, we've made a course correction, and you can write a Nexus plugin without learning any dependency injection framework. What has made this transition possible is the flexibility of Guice.
Stuart will dive into the technical details in the next five parts of this series. If you are interested in the implementation of Plexus and Guice, you'll find these posts to be a good starting point for learning about how we've implemented this compatibility layer.