Generate Dependency Graph for specific groupId - java

I am using the Depgraph Maven Plugin and I'd like to ask if there's a way to limit the generated graph file (dot or gml) with those with a specific groupId e.g. com.mycompany.* pattern where only the dependencies within this package would be part of the graph.
I have tried both depgraph:aggregate and depgraph:aggregate-by-groupid but both results contains all the dependencies only organized into groupId
Which generated this:

According to the README of the depgraph plugin (bottom of the page), you can use the includes/excludes parameters similar to Maven's dependency plugin. The plugin also provides more information on this in their filtering wiki page.
Parameters in Maven are provided with -D, or in the configuration of your plugin. In case of command line you would use:
mvn depgraph:graph -Dincludes=com.mycompany*

Related

Add property to maven archetype

I have a Maven archetype project and want to make some further things configurable. I tried:
Putting ${servicelocatorhost}$ and ${servicelocatorport} into my .tomcatplugin file.
Adding .tomcatplugin to the filtered files in the archetype metadata file.
Adding
<requiredProperties>
<requiredProperty key="servicelocatorhost">
<defaultValue>localhost</defaultValue>
</requiredProperty>
<requiredProperty key="servicelocatorport">
<defaultValue>2809</defaultValue>
</requiredProperty>
</requiredProperties>
to the archetype metadata file. When I build this, I get
Archetype IT 'basic' failed: Missing required properties in archetype.properties: servicelocatorhost, servicelocatorport
Until now I thought that the archetype.properties file is only for create-from-project but not building archetypes. Should I double the information for the properties and default values in such a file?
What exactly do I need to make this work?
When creating the archetype, there's also an integration test created for it. The values in the archetype.properties file are used when running the integration test (using the maven-invoker-plugin).
As an example: I have a simple archetype that filters a POM. In addition to GAV coordinates, I wanted the archetype user to provide the name of their Subversion repository and the application root directory so I could populate the <scm> block correctly. So I created variables ${scmRepo}, ${applicationRootDir}, and ${artifactId} in the archetype-metadata.xml file:
<requiredProperties>
<requiredProperty key="svnRepo" />
<requiredProperty key="applicationRootDir" />
<requiredProperty key="artifactId">
....
</requiredProperties>
then used them in the POM (src/main/resouces/archetype-resources/pom.xml):
<scm>
<connection>scm:svn:https://host.company.com/svn/${svnRepo}/trunk/${applicationRootDir}/${artifactId}</connection>
</scm>
The last step is to provide default values in the archetype.properties file. This is only used when you as the developer build the archetype, not when your community uses the archetype to create a project. It allows you to ensure the archetype does what you want. So in my example the archetype.properties file contains
svnRepo=maven
applicationRootDir=basic
artifactId=test
In the same directory, I have a verify.groovy file containing code to verify that the archetype worked correctly:
def xmlFile = new File(basedir, "pomFileDir/pom.xml")
assert xmlFile.exists()
def project = new XmlSlurper().parse(xmlFile)
....
assert "scm:svn:https://host.company.com/svn/maven/trunk/basic/test" == project.scm.connection.text()
I learned this from this blog post, this archetype documentation, and my own knowledge of using the Maven invoker plugin.

The Uniqueness of an artifactId in maven

Let's say that there are 2 maven artifacts (local) with the same
groupId but with a different artifactId.
The different artifactId should make each maven artifact unique.
However, if both of the unique artifacts each have a class with that share the same name. that class will not be unique because when it is imported to java it will use the groupId.className format. and the neither groupId nor the className are unique (in the discussed case).
This will result in an issue of ambiguity as to determining which class to use.
Upon testing it seems that the dependency declared first in the pom.xml file will be used.
The Question Are
What is the best practice solve/avoid this issue?
Why does maven's artifactId coordinate contribute to the uniqueness of a maven artifact within the repository but not inside the java code?
Example Code:
Maven - Same Class Name Same GroupId Different ArtifactId
Project1 is the first artifact.
Project2 is the second artifact.
"Projects User" is the artifact/project that will depend on both Project1 & Project2.
Project1 & Project2 both have a class named Utilities.
The class Utilities have a static method public static String getDescription() that returns a string containing the current project's artifact coordinates as well as the project name.
Utilities.getDescription() resulting String is called to see if an error will occur somewhere, and to see how it will be resolved.
The output depends on which dependency was declared first in the pom.xml file of the "Projects User" artifact.
Edited : Follow up Question
Is there an archetype that will create the java package using both the artifactId and groupId instead of having to do it manually every
time?
What is the best practice solve/avoid this issue?
We include the groupId and artifactId as the base package in the module. This way it is not possible to have the same class in two modules as the packages would be different.
e.g.
<groupId>net.openhft</groupId>
<artifactId>chronicle-bytes</artifactId>
has everything under the package
package net.openhft.chronicle.bytes;
Also if you know the package of a class you know which JAR it must be in.
if you have a class two JARs need, I suggest creating a common module, they both depend on.
Note: it is general practice to use your company domain name (and notional division as well) as the base of your package. Maven recommend using your domain name as you groupId and if you release to Maven Central this is now a requirement. The above strategy supports both recommendations.
Why does maven's artifactId coordinate contribute to the uniqueness of a maven artifact within the repository but not inside the java code?
Maven doesn't take any notice of the contents of the JAR.
#Peter following your lead on suggesting best practices to avoid this issue.
Group Id : It is required to uniquely identify your project. Revese of your domain name ex :
com.github.dibyaranjan
artifactId is the name of the jar without version.
To distinguish two classes from different JARs, Create package as groupId.artifactId.
For Example, I would create a project TestDummy, I want the name of the JAR to be TestDummy-1.1, then my package would look like.
com.github.dibyaranjan.testdummy
The class would look like - com.github.dibyaranjan.testdummy.MyClass
For reference visit : https://maven.apache.org/guides/mini/guide-naming-conventions.html

Maven Plugin: accessing resources accross multiple modules

I'm currently writing a custom maven plugin for generating a XML file in a multi-module maven project.
My maven structure is pretty standard: one parent project and a module by project components in the parent project folder:
-- Parent
-- module A
-- module B
-- module C
I need to list, by module, a set of classes flagged by a custom annotation.
I already wrote a set of custom annotations and an annocation processor to create a XML file at compile time in the corresponding module output directory (${project.build.outputDirectory}) .
Now i need to merge each module XML into one file, but i don't know how to access each modules from within my maven plugin except having each path set as parameters (i don't like this method).
Any idea on how to do this ?
Does maven plugins can traverse project modules ?
Thank you in advance.
To get the list list of all projects you can use:
List<MavenProject> projectList = MavenSession.getProjectDependencyGraph().getSortedProjects()
If one of your goals is correctly executed you will get everything you need. Every MavenProject contains a getBaseDir() etc.
After some researches, it seems that MavenProject.getCollectedProjects() will return the list of projects beeing manipulated by a goal execution in a multi-module project.

How to get jar library name and version from String library name?

I have many jar files in my directory:
some-lib-2.0.jar
some-lib-2.1-SNAPSHOT.jar
some-lib-3.RELEASE.jar
some-lib-R8.jar
some-lib-core-1.jar
some-lib-2.patch2.jar
some-lib-2-alpha-4.jar
some-lib.jar
some-lib2-4.0.jar
How can I get library name and version from file name?
Is regex ((?:(?!-\d)\S)+)-(\S*\d\S*(?:-SNAPSHOT)?).jar$ valid for extract name and version?
The version number in the JAR file name is merely a convention and a default for Maven-built JARs. It may have been overridden, and it is not always reliable reading the version number from just the file name.
A more reliable way for reading version number from JAR is to look inside the JAR file. Here you have a couple of options depending on how the JAR was built:
look at META-INF/maven/.../pom.properies and pom.xml and read the version from that - this should be present for Maven-built binaries
sometimes version number if present in META-INF/MANIFEST.MF under Specification-Version or Implementation-Version properties
If this fails, then fall back to reading version number from the JAR name since there is no other information available.
Naming policy could differ across different libraries, so you aren't able to extract name/version from package name using one rule, for details you should check project docs.
In case of Maven you are able to configure the final name of built artifact with finalName pom.xml configuration option. Maven docs provide nice introduction into pom structure. Below is the example from docs:
<build>
...
<finalName>${artifactId}-${version}</finalName>
...
</build>

Retrieving Maven Artifact from Repository using Maven Java API

If I have a Maven Artifact information (GroupId, ArtifactId, Version) how can I programmatically (using Java) retrieve that Artifact from my local repository?
Specifically, I need to be able to connect to the Maven Repository and create/retrieve a org.apache.maven.artifact.Artifact so I can retrieve the file associated with the Artifact.
I have looked into m2e source code, but the MavenImpl.java (which provides Artifact resolution) is way more complex than what I need and it is difficult to understand how the connection to the repository works.
You'll probably want to look at Aether. See the Wiki for examples.
You can construct a URL from the given information and download the file (note, replace the '.' in the <groupId> with '/'):
<repositoryUrl>/<groupId>/<artifactId>/<version>/<artifactId>-<version>.<type>
This is how we do it in jcabi-aether:
final File repo = this.session.getLocalRepository().getBasedir();
final Collection<Artifact> deps = new Aether(this.getProject(), repo).resolve(
new DefaultArtifact("junit", "junit-dep", "", "jar", "4.10"),
JavaScopes.RUNTIME
);
Give it a list of remote repositories, a location of a local repo, and Maven coordinates of the artifact. As the name shows, the library uses Apache Aether from Sonatype.

Categories