Colin Sampaleanu (Spring Framework, Interface21) brought again the topic about how to handle optional dependencies in Maven, what’s the best way, how to apply it,… You can read the thread How are people getting around the lack of custom scopes?. If you are too lazy and don’t want to reason you can skip to the end where you can find the solution for that problem under Maven 2.
The example he provides is Spring Webflow, currently packaged completely in an only jar, with some core dependencies always needed, some only needed when used with Spring MVC, some only with JSF, and some only with Struts.
While the idea of packaging a bunch of classes in one jar can be handy when you copy it manually I see more cons than pros:
- Almost everybody uses a tool that will deal with several jars with no problems
- Build time checking. If you include more classes than expected nothing prevents their use. This is a huge source of problems. My experience tells me that policies that can’t be enforced don’t succeed.
- Component Oriented design, if you find yourself including many dependencies in your pom is like importing a lot of stuff in a java class, not a great idea.
- With a transitive dependency tool like Maven you won’t need to add more than a few dependencies, eg depending on spring-hibernate3 automatically adds for you spring-core, spring-beans, spring-aop,…
- In fact the Spring guys gave a step in this direction in 2.0, splitting spring-hibernate (depending on hibernate 2 and 3) into spring-hibernate2 and spring-hibernate3, or spring-orm in different jars for each ORM implementation (JDO, Toplink,…)
Here you can see as example some of the problems that I found thanks to
Maven in the Spring Framework build, that can be found in the chapter Converting existing Ant builds in the book Better Buils With Maven, that I filed in the Spring Framework issue tracker.
It’s also worth to say that Acegi Security System for Spring has been building happily with Maven 1 for far more than a year and now is switching to Maven 2. Spring Rich Client is also building now with Maven 2.
If you still are not convinced about splitting your jars in small components based on your use cases (bad for you), here is the work around in Maven:
- Create a pom for your whole jar (spring-webflow), with all but core dependencies tagged as optional. You can build the jar with this pom.
- Create a pom for each of the configurations, setting packaging as pom, eg spring-webflow-spring-webmvc, spring-webflow-struts, spring-webflow-jsf
- To that poms add a dependency in spring-webflow and the required deps for that configuration
- spring-webflow-spring-webmvc -> spring-webflow, spring-webmvc
- spring-webflow-struts -> spring-webflow, struts
- spring-webflow-jsf -> spring-webflow, jsf
- In your application now you can depend on any of the projects in point #2 setting type to pom inside the dependency tag.
Hope you choose the right way and don’t go into the dark side 😉
FWIW we’re talking about very thin amount of integration code that integrates Spring Web Flow with MVC, and Struts: one class, FlowController, another class PortletFlowController, and another FlowAction. That’s it. JSF integration is a little more, but still quite small. The entire SWF library is 300K.
Don’t get me wrong I’m all for splitting out jar files when warranted, which is why spring-webflow-jar (~300K) is separate from another library it uses, spring-binding.jar (~60K). I’m just not sure it’s warranted here. Perhaps for the JSF integration.
That’s why the optional tag exists. It’s up to you guys to decide if for instance 1% of the users will need a dependency then you can make it optional and the user has to include it explicitly. In cases like spring-orm was a bad idea because 99% of the users only use one ORM framework.
Maven always allows you to choose, but it encourages a convention.