1

I'm having a problem reconciling building a project for use within an application server and for use as a stand-alone application.

To give an overall simplified context, say I have three Projects A, B, C.

Project A depends on Project B which depends on Project C.

Project C has a dependency X which is marked as provided since it was expected that it would be available as a JEE library within say an application server. i.e. jms.jar.

So if I perform an assembly build of Project A, I get all the transitive dependencies save for those marked as provided as expected.

Now I have a new deployment scenario where Project A needs to be used in a standalone environment i.e. outside an application server.

So now I need the jms jar to be a compile dependency. Does this mean that I should explicitly add a compile dependency for X in Project A? Doesn't this violate the Law of Demeter, i.e. don't talk to strangers, in the sense Project A shouldn't explicitly know about Project C but only about Project B?

This is a simple example but in reality I have multiple dependencies which have been marked as provided but are now need to be compile or runtime dependencies so they end up in the artifact produced by the maven assembly plugin.

Is this a fundamental problem with Maven or am I not using the tools correctly?

Thanks in advance for any guidance.

J Fabian Meier
  • 33,516
  • 10
  • 64
  • 142
Afrogeek
  • 121
  • 1
  • 1
  • 3

2 Answers2

0

Provided dependencies are a difficult subject. First of all: Provided dependencies are not transitive in the following sense: If your project C has a provided dependency on X, then A will not get the dependency. It is silently ignored. This fits with the following meaning of "provided" which I propose:

Only the artifacts that are actually deployed should mark dependencies as "provided". Libraries or other jars that are not individually deployed to a specific server should not have provided dependencies. Instead, they should declare their dependencies as compile dependencies. In your example: Project C should have a compile dependency on X. If project A knows that X is provided, it sets X to provided in "dependencyManagement". As project A should know the environment in which it runs it should decide what is provided and what is not. And "dependenyManagement" is the right place to declare this.

If your project A should be able to run within and without a given server, you probably need to make a lot of adjustments, even change the type from ear to jar. So you either use build profiles for this, which then have different dependencyManagement entries, or you split A into two projects which depend on some other project that contains the common elements.

If some given project C already has a provided dependency on X and you cannot change that, this is effectively the same as a missing dependency in C. This has to be repaired at some point, and this could be project A itself.

J Fabian Meier
  • 33,516
  • 10
  • 64
  • 142
0

If you need your build to have variations in it for different scenarios, you need to use profiles and keep certain things (such as some of the dependencies) in the various profiles.

http://maven.apache.org/pom.html#Profiles

Different dependencies for different build profiles in maven

answers a similar question - but you can swap in the "release" and "debug" for "Project A" and "Project C"

Community
  • 1
  • 1
Ryan
  • 584
  • 3
  • 13