You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@maven.apache.org by "G. Gustavo Pollitzer" <gg...@intelap.com> on 2011/10/28 23:21:18 UTC

scope management without losing granularity

¡Hello! I need to do something that, according to what I know, it is not 
supported by maven. Tell me if I am wrong.
Let BoM be a Bill of Materials (a POM with pom packaging type that, 
apart of the coordinates, only contains a <dependencyManagement> element 
which specifies the version of a bundle of artifacts).
Let A3 be an artifact contained in BoM (its version is specified in the 
<dependencyManagement> element of BoM).
Let A2 be third party artifact that depends on A3 with compile scope.
Let A1 be an artifact that depends on A2 also with compile scope.
Let E be POM that imports (or inherits from) BoM and whose 
<dependencies> element contains A1.
Suppose it is needed to override the scope of A3 in E. By example, 
change it to 'provided' because E packaging type is 'ear' and A3 is 
provided by the application server.
According to my knowledge, there is no proper way to override the scope 
of A3 without specifying its version nor losing granularity.
If I made use of the <dependencyManagement> element of E to override the 
scope of A3, I would be forced to specify an A3's valid version, and 
that opposes to the "Bill of Materials" pattern.
If I added A3 as another dependency of E with the desired scope, I would 
fall in the error of forcing E to depend on A3, fact that could be true 
in the current A2 version but may change in the future.
For the case of the example, the only solution I found is to put A3 as 
an excluded transitive dependency this way:
<code>
...
<artifactId>E</artifactId>
...
<dependencies>
     ...
<dependency>
<groupId>org.test</groupId>
<artifactId>A2</artifactId>
<excludes>
<exclude>
<groupId>org.test</groupId>
<artifactId>A3</groupId>
</exclude>
<excludes>
         ...
</dependency>
</dependencies>
...
</code>
The drawbacks of this approach are:
- It only solves the case of the mentioned example where the final 
objective is to avoid A3 be included in the "E.ear".
- If another artifact, call it X, depended on E with compile scope, it 
would (at least) throw compilation error if X tries to define a class 
that inherits from a class defined in A3.
- If E has many direct dependencies that transitively depend on A3, the 
exclusion would be necessarily and inconveniently repeated in all of them.

If I am not wrong and the above mentioned is not supported by maven, it 
occurred to me two improvements to solve it: To permit the 
<dependencyManagement> element to contain dependencies whose cordinates 
don't specify the version of artifacts that are already managed in a 
parent's of imported POM's <dependencyManagement> element; or to add a 
new kind of element inside the <dependencies> element to manage scope 
overrides. I prefer the second alternative because in the first some 
granularity is lost because the <dependencyManagement> element affects 
the children also.

I hope I am wrong and you illuminate my brain,

Happily,

Gustavo Pollitzer

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org


Re: scope management without losing granularity

Posted by Ron Wheeler <rw...@artifact-software.com>.
On 31/10/2011 3:39 PM, Gustavo Pollitzer wrote:
> Ron said:
>
>> *If a JAR does not contain all of the dependencies that it needs, a
>> person using that JAR must have some way to know what is missing and what
>> version is required.
>> They will only find out at run-time that this jar depends on a missing
>> dependency when the loader crashes.
>> The documentation of the utility will have to have big red sentences
>> describing each of the missing dependencies.
>> This will make it much harder for the IDE to help the programmer. Now the
>> IDE can detect version conflicts based on references in the POM and can let
>> the developer resolve them.*
>>
> I never said to skip the provided dependencies at all. What I suggested was
> to remove the 'provided' option from the<scope>  element in order to limit
> the POM creator to specify the requirements of the artifact only, and not
> hints of how his artifact and its dependencies are going to be assembled or
> deployed. Instead of 'provided' he has to use 'compile' or 'runtime'. This
> way the POM will contain all the necessary information needed but no more.
> Who determines what to assembly and/or how to deploy should be entirely the
> assembly module (the one with EAR packaging type by example). There is
> where the decisions on what to include in the assembly and how to deploy
> must be taken, and not before.
>
I understand your proposal. I am just not sure that you will not find 
out that this creates a whole new set of problems.

You have to remember that this is version 3 of Maven and it is used by 
thousands of people to develop many different sorts of applications.
The problem that you are addressing has been solved hundreds of times by 
Maven users producing EAR packages.

We just produce JARs and WARs in our application but the transitive 
dependency version problem and assembly construction issues are the same.

Ron

-- 
Ron Wheeler
President
Artifact Software Inc
email: rwheeler@artifact-software.com
skype: ronaldmwheeler
phone: 866-970-2435, ext 102



Re: scope management without losing granularity

Posted by Gustavo Pollitzer <gg...@intelap.com>.
Ron said:

> *If a JAR does not contain all of the dependencies that it needs, a
> person using that JAR must have some way to know what is missing and what
> version is required.
> They will only find out at run-time that this jar depends on a missing
> dependency when the loader crashes.
> The documentation of the utility will have to have big red sentences
> describing each of the missing dependencies.
> This will make it much harder for the IDE to help the programmer. Now the
> IDE can detect version conflicts based on references in the POM and can let
> the developer resolve them.*
>

I never said to skip the provided dependencies at all. What I suggested was
to remove the 'provided' option from the <scope> element in order to limit
the POM creator to specify the requirements of the artifact only, and not
hints of how his artifact and its dependencies are going to be assembled or
deployed. Instead of 'provided' he has to use 'compile' or 'runtime'. This
way the POM will contain all the necessary information needed but no more.
Who determines what to assembly and/or how to deploy should be entirely the
assembly module (the one with EAR packaging type by example). There is
where the decisions on what to include in the assembly and how to deploy
must be taken, and not before.

Re: scope management without losing granularity

Posted by Ron Wheeler <rw...@artifact-software.com>.
On 31/10/2011 2:13 PM, Gustavo Pollitzer wrote:
> Ron,
> Thanks again for your clarifications. Now, I have more clear that the
> plugins are free to give the understanding they wish to the POM elements.
> Even the plugins supported by the maven project.
>
> Anyhow, based on what you say, I believe you didn't understand me. Perhaps
> because my bad English.
>
> *On Mon, Oct 31, 2011 at 11:24 AM, Ron Wheeler<
> rwheeler@artifact-software.com>  wrote:
> *
>> *A plug-in that builds archives from artifacts created in other projects
>> will not care about scope since anything mentioned as a dependency or
>> included in the list of files to be included will be included.
>> The scope "provided" would be a stupid thing to say as a scope since you
>> could just leave it out of the list if you don't want it in the archive.
>> The scope "compile" is not instructive since you are not going to compile
>> anything.
>> I would expect the author of the plug-in to ignore scope altogether.*
>>
> The scope 'provided' is not pointless. It permits to exclude from the EAR
> an artifact that is a dependency of many of the artifacts that are listed
> for inclusion in the assembly. It avoid the necessity to add a transitive
> dependency exclusion in every expressly included artifact that can depend
> on it.
> In fact, how to do this the proper way was the question that incited me to
> start this discussion. But that is clear for me now.
This would be a particularity of the plug-in and could be true.
It seems that what you are saying is that the assembly plug-in will 
expand all of the jars and remove certain classes from the jars that 
have been marked as excluded.


> *
> On Mon, Oct 31, 2011 at 11:24 AM, Ron Wheeler<
> rwheeler@artifact-software.com>  wrote:
> *
>> *"Provided" only depends on deployment.
>> The fact that it is a "compile" or "provided" dependency at all means that
>> you need the artifact for the compile but when you specify a "provided"
>> dependency,  you are telling Maven that it will be provided at deployment
>> in some other way and you asking Maven NOT to stick it in the current
>> artifact.*
>>
> Right. But note that also the "compile" scoped dependencies are not
> packaged along the artifact in many packaging types.
In the "standard" Maven plug-ins that build jars, it will cause them to 
be included.
> Anyway, that is what I am trying to say. This is the information supplied
> by the second aspect of the<scope>  element I mentioned. This aspect tells
> maven how the dependency will be provided.

> And because the person that
> creates an artifact POM (in opposition to an assembly POM) doesn't have to
> take care if his artifact and the dependencies it requires are going to be
> assembled together or how are they deployed, it should not be specified in
> the artifact's POM.
An interesting point.
If a JAR does not contain all of the dependencies that it needs, a 
person using that JAR must have some way to know what is missing and 
what version is required.
They will only find out at run-time that this jar depends on a missing 
dependency when the loader crashes.
The documentation of the utility will have to have big red sentences 
describing each of the missing dependencies.
This will make it much harder for the IDE to help the programmer. Now 
the IDE can detect version conflicts based on references in the POM and 
can let the developer resolve them.
> The artifact POM merely has to tell maven which dependencies are required
> by the release, which are required for testing, which of them are required
> during runtime only or compilation also, and which of them must be loaded
> by the same class loader than the artifact classes. In short, what it
> requires.
>
> On the other hand, the assembly POM provides the requirements and/or tells
> how they are provided.
> Therefore, the 'provided' option (and much more the 'system' option) must
> be removed from the<scope>  element. This information pertains to the
> assembly POM or whatever specifies how to deploy.

System is never used.

> I hope I was clearer this time.
I understand where the motivation for this idea comes from but am 
concerned that the problem that it creates is worse than the problem 
that it solves.

We used a much clearer way of solving this problem through aggregation 
jars that sorted out deployment once for each set of libraries and 
reduced the artifact POMs' <dependencies> to a few dependencies that 
were carefully managed centrally.


Ron

-- 
Ron Wheeler
President
Artifact Software Inc
email: rwheeler@artifact-software.com
skype: ronaldmwheeler
phone: 866-970-2435, ext 102



Re: scope management without losing granularity

Posted by Gustavo Pollitzer <gg...@intelap.com>.
Ron,
Thanks again for your clarifications. Now, I have more clear that the
plugins are free to give the understanding they wish to the POM elements.
Even the plugins supported by the maven project.

Anyhow, based on what you say, I believe you didn't understand me. Perhaps
because my bad English.

*On Mon, Oct 31, 2011 at 11:24 AM, Ron Wheeler <
rwheeler@artifact-software.com> wrote:
*
>
> *A plug-in that builds archives from artifacts created in other projects
> will not care about scope since anything mentioned as a dependency or
> included in the list of files to be included will be included.
> The scope "provided" would be a stupid thing to say as a scope since you
> could just leave it out of the list if you don't want it in the archive.
> The scope "compile" is not instructive since you are not going to compile
> anything.
> I would expect the author of the plug-in to ignore scope altogether.*
>

The scope 'provided' is not pointless. It permits to exclude from the EAR
an artifact that is a dependency of many of the artifacts that are listed
for inclusion in the assembly. It avoid the necessity to add a transitive
dependency exclusion in every expressly included artifact that can depend
on it.
In fact, how to do this the proper way was the question that incited me to
start this discussion. But that is clear for me now.
*
On Mon, Oct 31, 2011 at 11:24 AM, Ron Wheeler <
rwheeler@artifact-software.com> wrote:
*
>
> *"Provided" only depends on deployment.
> The fact that it is a "compile" or "provided" dependency at all means that
> you need the artifact for the compile but when you specify a "provided"
> dependency,  you are telling Maven that it will be provided at deployment
> in some other way and you asking Maven NOT to stick it in the current
> artifact.*
>

Right. But note that also the "compile" scoped dependencies are not
packaged along the artifact in many packaging types.
Anyway, that is what I am trying to say. This is the information supplied
by the second aspect of the <scope> element I mentioned. This aspect tells
maven how the dependency will be provided. And because the person that
creates an artifact POM (in opposition to an assembly POM) doesn't have to
take care if his artifact and the dependencies it requires are going to be
assembled together or how are they deployed, it should not be specified in
the artifact's POM.
The artifact POM merely has to tell maven which dependencies are required
by the release, which are required for testing, which of them are required
during runtime only or compilation also, and which of them must be loaded
by the same class loader than the artifact classes. In short, what it
requires.

On the other hand, the assembly POM provides the requirements and/or tells
how they are provided.
Therefore, the 'provided' option (and much more the 'system' option) must
be removed from the <scope> element. This information pertains to the
assembly POM or whatever specifies how to deploy.

I hope I was clearer this time.

Re: scope management without losing granularity

Posted by Ron Wheeler <rw...@artifact-software.com>.
On 30/10/2011 5:56 PM, Gustavo Pollitzer wrote:
> Thank you a lot for your time. Your really illuminated my brain. My mistake
> was to try to make the EAR module of my project in such a way that other
> artifacts can depend on it. But that is no the purpose of EAR modules.
Right.
> So, there is no risk to append, after the dependencies intended to add
> content to the EAR, some dependencies to artifacts that are already
> dependencies of the before dependencies just to override its scope to
> 'provided'. The maven-ear-plugin takes advantage of the maven dependency
> management, but uses it for a very different purpose: to make an archive
> and not an artifact to which other artifacts can depend upon. So the
> maven terms has a different meaning in POMs intended to be an artifact to
> which others can depend upon than in POMs intended to build assemblies.
That could be but that is the plug-in author's choice.
The assembly plug-in or the shade plug-in can use a separate file to 
determine what to include in the archive.

> Nevertheless, there is something that makes noise in my brain. It would be
> better if the two kinds of dependencies; the ones intended to add content
> to the EAR, let's call them 'content' dependencies, and the ones intended
> to override the scope of the dependencies of the 'content' dependencies;
> would be clearly distinguishable by means of the maven language instead
> of comments.

A plug-in that builds archives from artifacts created in other projects 
will not care about scope since anything mentioned as a dependency or 
included in the list of files to be included will be included.
The scope "provided" would be a stupid thing to say as a scope since you 
could just leave it out of the list if you don't want it in the archive.
The scope "compile" is not instructive since you are not going to 
compile anything.
I would expect the author of the plug-in to ignore scope altogether.

>
> I think that the source of this trouble is the low cohesion of the<scope>
> element. It tries to specify two aspects of an artifact with a single
> value. Two aspects that should be independent of each other and that should
> be determined in different circumstances.
>
>     - The first aspect is the classification of the dependency as
>     required during runtime only or during compilation also. This aspect
>     depends only and exclusively on the source code of the artifact for which
>     we are specifying the dependencies. It does not depend in any way on the
>     deployment.
Not true.
"Provided" only depends on deployment.
The fact that it is a "compile" or "provided" dependency at all means 
that you need the artifact for the compile but when you specify a 
"provided" dependency,  you are telling Maven that it will be provided 
at deployment in some other way and you asking Maven NOT to stick it in 
the current artifact.

>     - And the second aspect tells the packager plugin if it has to add the
>     dependency to the archive or not. This aspect has nothing to do with the
>     source code, but only with the deployment. The creator of the artifact
>     should not necessarily know the way his artifact and their dependencies
>     will be deployed, and therefore, this aspect should not be specified by
>     him, but by responsible of the deployment trough some kind of descriptor.
>     In our case, the EAR module POM.
>
This depends on who wrote the plug-in and what they decided to use as 
instructions.
This has nothing to do with Maven since anyone can put whatever logic 
they want in their plug-in.
If the plug-in has its own place to list files and artifacts that it 
want to manipulate, that will work.
If the author wants to look at the <dependencies> to identify artifacts 
to process, that will work.

Don't mix up plug-ins with Maven and be careful about generalizing the 
behaviour of plug-ins.
The author has a lot of freedom about how to build a plug-in.
There is a big difference between the core Maven plug-ins that compile 
and build artifacts and plug-ins that do assemblies of archives.
You are right that their understanding of <dependencies> are very different.

I hope that this helps.

Ron


-- 
Ron Wheeler
President
Artifact Software Inc
email: rwheeler@artifact-software.com
skype: ronaldmwheeler
phone: 866-970-2435, ext 102



Re: scope management without losing granularity

Posted by Gustavo Pollitzer <gg...@intelap.com>.
So, I still believe that maven needs improvements in this sense. In my
opinion:

   - The <scope> element should be limited to tell only if the dependency
   is required during run-time only or during compilation also. Whenever to
   include the dependency in an assembly or not should be delegated to the the
   descriptor of the assembly. The EAR POM by example.
   - A new sub element of the <dependency> element should be added to
   specify if the code of the artifact supports that the classes in the
   dependency can be loaded by a different class loader or not.
   - The content of the packages like EAR, that are not intended to be
   depended upon, should not be determined by the <dependencies> element but
   by a new element with a different structure. A structure that allows to
   exclude a single and a bundle of transitive dependencies from both, a
   single component and a group of them. To use the same structure to specify
   two so different things causes ambiguities and/or limitations.

Re: scope management without losing granularity

Posted by Gustavo Pollitzer <gg...@intelap.com>.
Thank you a lot for your time. Your really illuminated my brain. My mistake
was to try to make the EAR module of my project in such a way that other
artifacts can depend on it. But that is no the purpose of EAR modules.
So, there is no risk to append, after the dependencies intended to add
content to the EAR, some dependencies to artifacts that are already
dependencies of the before dependencies just to override its scope to
'provided'. The maven-ear-plugin takes advantage of the maven dependency
management, but uses it for a very different purpose: to make an archive
and not an artifact to which other artifacts can depend upon. So the
maven terms has a different meaning in POMs intended to be an artifact to
which others can depend upon than in POMs intended to build assemblies.

Nevertheless, there is something that makes noise in my brain. It would be
better if the two kinds of dependencies; the ones intended to add content
to the EAR, let's call them 'content' dependencies, and the ones intended
to override the scope of the dependencies of the 'content' dependencies;
would be clearly distinguishable by means of the maven language instead
of comments.

I think that the source of this trouble is the low cohesion of the <scope>
element. It tries to specify two aspects of an artifact with a single
value. Two aspects that should be independent of each other and that should
be determined in different circumstances.

   - The first aspect is the classification of the dependency as
   required during runtime only or during compilation also. This aspect
   depends only and exclusively on the source code of the artifact for which
   we are specifying the dependencies. It does not depend in any way on the
   deployment.
   - And the second aspect tells the packager plugin if it has to add the
   dependency to the archive or not. This aspect has nothing to do with the
   source code, but only with the deployment. The creator of the artifact
   should not necessarily know the way his artifact and their dependencies
   will be deployed, and therefore, this aspect should not be specified by
   him, but by responsible of the deployment trough some kind of descriptor.
   In our case, the EAR module POM.

Re: scope management without losing granularity

Posted by Barrie Treloar <ba...@gmail.com>.
On Sun, Oct 30, 2011 at 4:50 AM, Ron Wheeler
<rw...@artifact-software.com> wrote:
> If you want to continue the conversation, you should maybe tell everyone a
> bit about what you are trying to build and why your application structure
> has to be so different from everyone else building the same type of
> application.
> That will get you much better advice since there are probably dozens of
> people in the forum who have built applications to run in exactly the same
> environment.
> If you can tell them where you are deviating from the standard structure,
> they may be able to give you some good advice.
> If you are building a normal web application that runs in one of the normal
> environments, Maven will work very simply as is.

And I will add to Ron's advice - have a read of the free books available at
http://maven.apache.org/articles.html

> According to my knowledge, there is no proper way to override the scope of A3 without specifying its version nor losing granularity.
Also as Ron says you want to have the correct scope defined the first
time so that you only need to override it once for you "library"
artifact.
It is definitely possible to only specify group and artifact with the
new scope to change what was defined in dependencyManagement.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org


Re: scope management without losing granularity

Posted by Ron Wheeler <rw...@artifact-software.com>.
Your example is a little complicated and not exactly expressed in Maven 
terms but I can respond to a bit of what you wrote.

In general, you might want to start with what you are trying to build.
Maven is used by thousands on people to build many different types of 
applications.
Maven enforces a certain way of looking at the universe and will defeat 
you (or make you wish you gave up) if you try to fight it.

See below for specific comments

On 28/10/2011 5:21 PM, G. Gustavo Pollitzer wrote:
> �Hello! I need to do something that, according to what I know, it is 
> not supported by maven. Tell me if I am wrong.
> Let BoM be a Bill of Materials (a POM with pom packaging type that, 
> apart of the coordinates, only contains a <dependencyManagement> 
> element which specifies the version of a bundle of artifacts).
> Let A3 be an artifact contained in BoM (its version is specified in 
> the <dependencyManagement> element of BoM).
> Let A2 be third party artifact that depends on A3 with compile scope.
> Let A1 be an artifact that depends on A2 also with compile scope.
> Let E be POM that imports (or inherits from) BoM and whose 
> <dependencies> element contains A1.
> Suppose it is needed to override the scope of A3 in E. By example, 
> change it to 'provided' because E packaging type is 'ear' and A3 is 
> provided by the application server.
> According to my knowledge, there is no proper way to override the 
> scope of A3 without specifying its version nor losing granularity.
> If I made use of the <dependencyManagement> element of E to override 
> the scope of A3, I would be forced to specify an A3's valid version, 
> and that opposes to the "Bill of Materials" pattern.
> If I added A3 as another dependency of E with the desired scope, I 
> would fall in the error of forcing E to depend on A3, fact that could 
> be true in the current A2 version but may change in the future.
> For the case of the example, the only solution I found is to put A3 as 
> an excluded transitive dependency this way:
> <code>
> ...
> <artifactId>E</artifactId>
> ...
> <dependencies>
>     ...
> <dependency>
> <groupId>org.test</groupId>
> <artifactId>A2</artifactId>
> <excludes>
> <exclude>
> <groupId>org.test</groupId>
> <artifactId>A3</groupId>
> </exclude>
> <excludes>
>         ...
> </dependency>
> </dependencies>
> ...
> </code>
> The drawbacks of this approach are:
> - It only solves the case of the mentioned example where the final 
> objective is to avoid A3 be included in the "E.ear".
> - If another artifact, call it X, depended on E with compile scope, it 
> would (at least) throw compilation error if X tries to define a class 
> that inherits from a class defined in A3.
If X has a dependency on Y, then it should either define the dependency 
itself or depend on something that exposes Y. Having it depend on a 
project E that excludes Y will not get you Y.
> - If E has many direct dependencies that transitively depend on A3, 
> the exclusion would be necessarily and inconveniently repeated in all 
> of them.
Not sure that is needs to be true.
You can fix this by building proper libraries that contain exactly what 
you want and depend on them.
Probably A3 needs to a "provided" scope dependency in A2 and provided to 
all modules once, in a library POM or an application 'core' library that 
gets you the common stuff.
Then you don't need the exclusion since it is not included in A2.


http://blog.artifact-software.com/tech/?p=121

> If I am not wrong and the above mentioned is not supported by maven, 
> it occurred to me two improvements to solve it: To permit the 
> <dependencyManagement> element to contain dependencies whose 
> cordinates don't specify the version of artifacts that are already 
> managed in a parent's of imported POM's <dependencyManagement> 
> element; or to add a new kind of element inside the <dependencies> 
> element to manage scope overrides. I prefer the second alternative 
> because in the first some granularity is lost because the 
> <dependencyManagement> element affects the children also.
>
I would focus on getting your project properly structured and working.
It takes a while to figure out Maven if you come at it very fixed ideas.
First figure out why Maven is doing it the best possible way and what 
your project structure should be to get the most out of Maven.
You will likely find that your request is not a good idea.

We have several large portal applications (70+ modules with over 100 
third party libraries) and Maven works very effectively in this 
environment with very small POM files with no custom plug-ins or any 
fancy stuff.


> I hope I am wrong and you illuminate my brain,
You probably are.

If you want to continue the conversation, you should maybe tell everyone 
a bit about what you are trying to build and why your application 
structure has to be so different from everyone else building the same 
type of application.
That will get you much better advice since there are probably dozens of 
people in the forum who have built applications to run in exactly the 
same environment.
If you can tell them where you are deviating from the standard 
structure, they may be able to give you some good advice.
If you are building a normal web application that runs in one of the 
normal environments, Maven will work very simply as is.

I hope that this helps.


>
> Happily,
>
> Gustavo Pollitzer
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
> For additional commands, e-mail: users-help@maven.apache.org
>
>


-- 
Ron Wheeler
President
Artifact Software Inc
email: rwheeler@artifact-software.com
skype: ronaldmwheeler
phone: 866-970-2435, ext 102