Accessing a property of a sibling project dependency - maven-2

Let's say I have
<properties>
...
<module.deployPath>/admin</module.deployPath>
...
</properties>
in the pom.xml of the project A.
And now I'd like to access ${module.deployPath} in another project B where project A is listed as dependency of project B.
Is this possible somehow without using external property files or settings.xml?
Thank you for your help!
Cheers,
b

Staying strictly within Maven's property access mechanism, I'm almost certain you can't do that. If you were to add the GMaven plugin and write some Groovy code, then it would probably be possible to get and parse the dependency's pom to get at the property you're looking for.

Related

Disable transitive PackageReference dependency for a specific MsBuild project

I am migrating an old style MsBuild csproj project to using PackageReference format and have run into a problem with transitive dependencies.
Consider the following
Project A reference NuGet package B and C, each containing one single assembly using PackageReference.
On Build Project A uses IL merge to incorporate B as public symbols in the A assembly and C as internalized symbols.
Project D have a project reference to A.
The transitive dependencies case D to reference A, B and C.
When building D, compile errors of the type
error CS0433: The type 'X' exists in both 'A' and 'B'
occur.
Is there any way to force D to not add an explicit reference to B or C in the scenario above?
Disable transitive PackageReference dependency for a specific MsBuild project
If I understand you correct, you can try to use property <PrivateAssets>all</PrivateAssets>or PrivateAssets="all" for the PackageReference. If you have a package that's marked with private assets it merely prevents it from flowing to parent project or getting packed.
<PackageReference Include="B" Version="1.0.0" PrivateAssets="all">
<PackageReference Include="C" Version="1.0.0" PrivateAssets="all">
You can check the document Controlling dependency assets and this thread for some details.
Hope this helps.
I ended up using a workaround to move the transitive dependency to an alias to get around the compiler error.
<Target Name="ChangeAliasesOfBNameAssemblies" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
<ItemGroup>
<ReferencePath Condition="'%(FileName)' == 'B'">
<Aliases>nonmerged</Aliases>
</ReferencePath>
</ItemGroup>
</Target>
I tried to use private assets but couldn't get the compiler error to go away in that way.
I was looking for this too and this answer kept popping up in google searches, but it didn't have the solution I know off (but can never remember), so I'll add my answer for future reference.
PrivateAssets can be used to hide many things, but hiding all is a bad move imo. You want some assets to move transitively, for example, for your app to run after a dotnet publish, you'll need the assemblies you need, at runtime. Hiding all assets means that when publishing, you may miss a few critical things - similar to deleting some files from the output.
From reading MS docs on the subject, I think what I want to hide, in order to not transitively be able to compile up against an assembly (but still have it at runtime), is compile. So I'll set my PrivateAssets to contentfiles;analyzers;build;compile. This should mean that if MyLibraryB depends on NugetPackageA - then MyAppC depending on MyLibraryB will be able to run and publish correctly, without being able to use any classes or code from NugetPackageA.
Note: This of course means that MyLibraryB must not expose any public API that uses types found in NugetPackageA. The consumer won't be able to use those public API's, at least not without themselves also referencing NugetPackageA.

How to set the orders of jars in Weblogic EAR?

I have an EAR file that contains two different jars that share some classes with an identical package+class name. This results in importance of classloading inside the EAR file itself.
How can I tell Weblogic to load one jar from APP-INF/lib before loading a different one in the same APP-INF/lib? I need to define a specific order to that if there is a conflict, it will take from JAR a and not JAR b.
I'm using Webogic 11g (10.3).
Thanks.
The top-level element in weblogic-application.xml has an optional classloader-structure element that you probably want to look into. For instance you can do something like:
<classloader-structure>
<module-ref>
<module-uri>ejb1.jar</module-uri>
</module-ref>
<module-ref>
<module-uri>web3.war</module-uri>
</module-ref>
<classloader-structure>
<module-ref>
<module-uri>web1.war</module-uri>
</module-ref>
</classloader-structure>
</classloader-structure>
Read more about declaring custom class loading at these Oracle docs. You may also find the Classloader Analysis Tool (CAT) at the same link of interest.
If you're getting ClassNotFound exceptions, try checking out the MANIFEST.MF for each of your modules to see if the "Class-Path" attribute is correctly populated with the locations of your jars in your APP-INF/lib - I've just spent a week or more tearing my hair out trying to find a solution to a similar problem, and this is what fixed it.

Maven module properties from another module

I have a multi-module project. In one of the modules I'm generating classes from wsdl. In the pom of this module I need some properties of another module. (build.directory, outputDirectory etc)
It something like this possible?
${project.parent.module.0.build.directory}
I think I saw the above somewhere. Didn't bother testing it because doing module.0 would mean it's dependent on the order in which modules are declared in the parent pom.
Is there a elegant way of doing what I want?
The proper way to do this is to have a parent. Define the properties in there and then simply use that as the parent in your other modules. That way you can easily share the properties across your modules.
Maven doesn't provide this kind of access. You could use Groovy via GMaven to parse the other pom as XML and get at what you want.

How to find unneccesary dependencies in a maven multi-project?

If you are developing a large evolving multi module maven project it seems inevitable that there are some dependencies given in the poms that are unneccesary, since they are transitively included by other dependencies. For example this happens if you have a module A that originally includes C. Later you refactor and have A depend on a module B which in turn depends on C. If you are not careful enough you'll wind up with both B and C in A's dependency list. But of course you do not need to put C into A's pom, since it is included transitively, anyway. Is there tool to find such unneccesary dependencies?
(These dependencies do not actually hurt, but they might obscure your actual module structure and having less stuff in the pom is usually better. :-)
To some extent you can use dependency:analyze, but it's not too helpful. Also check JBoss Tattletale.
Some time ago I've started a maven-storyteller-plugin to be able to deeper analyze the poms, but the project is very far from production/public use. You can use the storyteller:recount goal to analyze the unused/redundant dependencies.
The problem with the whole story is - how to determine "unused" things. What is quite possible to analyze is for instance class references. But it won't work if you're using reflection - directly or non-directly.
Update November 2014.
I've just moved my old code of the Storyteller plugin to GitHub. I'll refresh it and release to the central so that it's usable for others.
I
personaly use the pom editor of M2Eclipse to visually view the dependency tree (2D tree). Then I give a look in my deliverable (war, ear) lib directories. Then still in M2Eclipse pom dependencies viewer I go to every 3rd party, and right click on the dependency I want to exclude (an exclusion is added automatically in the right dependency).
There is no golden rules, simply some basic tips:
a lot of pom are not correct: a lot of 3rd party libs out there require way too much dependencies in the default compile scope, if everybody carefully craft their pom, you must not have so much unwanted dependencies.
you need to guess by the name of dependencies what you will have to exclude, best example are parsers, transformer, documentbuilder: xalan, xerces, xalan alfred and co. try to remove them and use the internal jdk1.6 parser, common apache stuff, log4j is also worth looking at.
look also regularly in lib delivery if you do not have duplicate libraries with different version (the dependency resolver of maven should avoid that)
go bottom up, start with your common modules, then go up till the service layer, trimming down dependencies in every module, dont try to start in modules ear/war, it will be too difficult
check often if your deliverable are still working, by either testing or comparing and old deliverable with the new one (especially in web-inf/lib directory what has disappeared with winmerge/beyoncompare)
When you have A -> B, B -> C, and then refactor such that A -> (B, C). IF it is the case that A still compiles against B, you very much don't want to simply pick up the dependency because you receive it transitively.
Think of the case when A -> (B-1.0, C-1.0), B-1.0 -> C-1.0. Everything's in sync, so to avoid "duplication" you remove C from A's dependency. Then you upgrade A to use B-2.0 -> C-2.0. You begin to see errors because A wants C-1.0 classes but found C-2.0 classes. While quickly reconcilable in this scenario, it is far less so when you have lots of dependencies.
You very much want the information in A's pom that says that it explicitly expects to find C-1.0 on the classpath so that you can understand when you have transitive dependency conflicts. Again, Maven will do the job of ensuring that the "closest" version of any particular jar ends up on your classpath. But when things go wrong - you want all the dependency metatdata you can get.
On a slightly more practical note, a dependency is unused when you can remove it from your pom and all of your unit/integration/acceptance tests still pass. ;-)

Hierarchy of maven projects without scattering the version number

If you use Maven2 as a build system for a project containing many artefacts with the same version number, you have the version of the resulting build scattered in all pom.xml. In many of them even twice - in the version tag of the artefact itself and in the version tag of the parent. Thus, you have to change and check in new versions of all pom.xml on every version switch. This is somewhat annoying, especially if you have to code for several bug fixing and a development version in parallel. Is there a way around that?
CLARIFICATION: My question is about the many versions of every single pom.xml that you get over time in your source control system that differ only by the version number of the pom and / or the version number of the parent pom. Ideally, you should only need to change the pom whenever you add a dependency or something.
For example you have a project with the artifacts foo-pom (the parent pom to all), foobar-jar, foobaz-jar and foo-war. In the first release the version is 1.0 - which appears in every pom.xml. In the second release the version is 1.1 - which again appears in every pom.xml. So you have to change every pom.xml - this is annoying if you release as often as you should.
UPDATE: If you think this is important: not having to specify the parent version is already being considered. Please go to the maven JIRA issue and vote for it to get it more noticed and more likely to be added as an enhancement in an upcoming release. You need to create/have a JIRA login for that.
There is another Stackoverflow Question that is basically about the same problem.
There's another StackOverflow thread that also covers this topic that you might want to look at.
In short, not having to specify the parent version when using inheritance is already being considered. Please go over to JIRA and give it a vote bump to get it more noticed and more likely to be added as an enhancement in an upcoming release.
I've run into similar problems while working on a large system built with Maven 2.
In my opinion, the downside of the typical multi-module structure is that all modules
have to share the same version. This is indeed annoying: even if your
next release only consists in a bugfix in foobar-jar, you need to
change the global version everywhere (be it manually or with
maven-release-plugin) and roll a new release of every component. In my case, I built various WAR/EAR applications, so my customer would ask me why I delivered a new version of both app1 and app2, when only app1 was supposed to be impacted.
The opposite approach is to manage each component as an independent
project, with its own independent version. This is more flexible as it
allows partial releases, but you now need to track all these versions
manually (know which versions your next delivery will consist in, make
sure internal dependencies are consistent, etc.). This can quickly
become a nightmare in a large application.
I've long thought about a way to combine both approaches: the flexibility of independent versions, without giving up the global coherency of the system. I tried the same approach as romaintaz, and ran into the same problem. Finally, I came up with this idea:
http://out-println.blogspot.com/2008/10/maven-modules-with-independent-versions.html.
Consider it as 'experimental', as I didn't get to try it live in the end (for non-technical reasons). But I think it would do the trick.
On my project, I have such a problem. To reduce the number of versions I define in my parent pom.xml some properties, which correspond to the versions of each module:
<properties>
<project-version>1.0.0</project-version>
<!-- Same version than the parent for the module 'commons' -->
<project-commons-version>${project-version}</project-commons-version>
<!-- A specific version for the 'business' module -->
<project-business-version>1.0.1</project-business-version>
...
And then, in the pom.xml of each module, I use these properties.
The problem is that I must clearly input the version of the parent in this pom.xml.
For example, in my business pom.xml, I have:
<project>
<modelVersion>4.0.0</modelVersion>
<!-- I must indicate the version of the parent -->
<parent>
<groupId>my.project</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
...
<dependencies>
<!-- However, in my dependencies, I use directly the properties defined in the parent's pom.xml -->
<dependency>
<groupId>my.project</groupId>
<artifactId>project-persistence</artifactId>
<version>${project-persistence-version}</version>
</dependency>
However, I really suggest that you have a look to the release plugin that will take care of modifying all the version numbers for you.
Does this article provide a solution for your problem ?
The idea is to declare the version number for the whole project as a property, namely "aversion" (pun intended), in the parent pom. The parent pom's own version number can be anything as long as it ends with "SNAPSHOT".
Child modules' version is specified via the ${aversion} property. Children's reference to their parent's version is hard coded. However, since the parent pom's version is a SNAPSHOT, child modules will see the changes in the parent pom. In particular, if the parent pom changes the value of ${aversion}, the children will see the change.
Not a perfect solution according to the comments.
And the release plugin doesn't solve the real problem: merging.
Having endless copies of the version number all over the place means lots of conflicts when bringing branches back together.
Note:
with Maven 2.0.9 (latest one - April 2008) I have simply been omitting the version element from the individual modules as they will inherit the version from their parent. This works with the groupId as well if your modules share the same groupId as their parent.
This is an idea for a possible extension of maven that would solve the problem.
Currently you have to write the a version of the artifact and of the parent pom in the pom.xml. There already is a way to give an absolute location for the parent pom:
<parent>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<relativePath>../my-parent</relativePath>
</parent>
If you allow omitting of both the version of the parent and of this pom iff maven is able to access the parent pom by the relative path, you are done. The version is only mentioned in the parent pom and nowhere else.
We have exactly this problem. We have a a large number (around 10) of different projects some of which depend on each other. The folder containing the projects has a parent pom for the entire set of projects. Each time we created a new branch we had to go into each and every pom file to change the <version> element and also the <version> for the parent, and all this editing was annoying.
After reading this question and the answers here I realized that the situation was hopeless. Each project could inherit the <version> element from the parent pom so that one was easy to eliminate, but we obviously could not inherit the <version> for the <parent>.
Unfortunately, I forgot to tell my colleague it was impossible, so he fixed it. His solution was to add a property to the parent pom file:
<properties><currentVersion>2.6.1-SNAPSHOT</currentVersion></properties>
Then in the child pom files we declared the parent version tag like this:
<version>${currentVersion}</version>
I don't know why this works. I don't see how it can find the right parent pom without specifying the version number. But for me (maven version 1.5.0_22) it is working.
Here is another lightweight workaround until the maven issue is resolved. In one large project we do no longer put the pom.xml itself in the version control, but a pom-template.xml which just contains a placeholder for the version number. After updating the project tree from version control you need to run a little ant script that generates the actual pom.xml in every directory. This is annoying, but less annoying than to have to put up with all those bothersome pom versions.