I noticed there's already a dependency on velocity - that's great news
since I had hoped to replace a lot of ugly java code with a template. If
nothing else it would be easier to maintain. It's let me do some rapid
prototyping with the goal of both finding the best presentation (at least
for me) and to identify and remove unnecessary code. I have to step away
from other tasks for a few days but should have something good enough for a
POC pull request by early next week. This can also include sample output -
I've been focused on correctness over brevity and the current
implementation is creating images too large to attach here. (The brevity
would be handled by omitting default values and reducing whitespace - the
latter makes it easier to read by with 100+ dependencies it can make the
difference between whether something can be attached to email or not.

This will require the addition of at least one new property -
'templateName'. It can be optional (use a defautt template), or a
predefined one. It may be too risky to allow the user to specify an
arbitrary file, esp. since it's easy to clone the project and add your own
template(s) to the jar. The same thing applies to the velocity macro
libraries - they make it very easy to separate the structural and
presentation elements but allowing inclusion of arbitrary macros would be a
security risk.

Proposed code changes

1. There's a new package - org.apache.maven.dependency.utils.templates.
It's generic (templates, not velocity) so it's easy to add additional
template engines in the future.

2. There's a few new classes. I have an extended NodeProperties for a few
values that only make sense in this context, e.g., the 'port' used in the
dot 'edges'. I suspect it will be easiest to just add one or two new
properties to that class.

3. The second new class is similar to NodeProperties but is focused on the
groupId instead of the individual dependencies. For now this is in
'templates' but it might make sense to move it.

4. The third new class contains configurable style information. Fontnames
and sizes, colors to use, etc. Hmmm... this could also be handled via a
velocity macro...

5. Plus the helper class that actually creates and initializes the Velocity
engine and produces the final results.

There's also new resources - /templates/{format}/{templateName}. 'format'
would be 'dot', 'json', etc. We could add 'velocity' to the path but I
don't think that's necessary since there's no other templating engines on
the horizon and the fomats can be identified by file extension (.vm, .j2,
...)

Plus...

I'm always looking at the list of dependencies. I know this is a standalone
app, not a long-running service, so there's not the same risks when you
have a long list of dependencies. However I think it's still worth
considering since maven is so widely used in CI/CD pipelines.

I mentioned 'structural' vs 'presentation' aspects earlier. I don't know
how widely jackson is used but if it's only used to generate the JSON
output then it should be easy to replace that with a velocity template.
PARSING JSON has lots of dragons but GENERATING it is a lot easier, esp.
with the simple data structures used here.

The same thing may be true of GraphML and the other formats.

Plus...

The more I look at this the more I think there should be a clear
recognition that both list and tree formats should support both "by maven
dependency" and "by package name" layouts. For lists it would be a simple
sort by groupId.  That makes it easy to check for consistent versions. For
trees the basic element would be each groupId with the artifacts in a
simple table. These blocks can still be ranked by the highest rank element.
I'm still experimenting with the dependency edges but it looks like a link
to the groupId's table, vs. individual artifacts, is a good balance between
seeing the maven dependencies vs. clutter. Ditto removing all dependencies
within a groupId. It may be possible to retain the outward bound link from
individual artifactId to the groupId.

This raised the possibility of a few new options.

The first is the ability to specify an arbitrary dependency (or groupid?)
as the root of the tree. For instance Jackson is built from multiple
modules and with this approach the exact dependencies will be lost. If we
can have a graph of just the Jackson interdependencies or the Jackson
dependencies + external dependencies it would make the trees even more
useful since they'll be small enough and focused enough to add to the
javadoc, package-info, or potentially even a standalone image in the source
directory. (I'm starting to inclulde README.md files since they're so
easily seen when browsing github in a browser.)

The second is the ability to collapse (groupId) dependencies. You might be
interested in the full tree but don't care about the details of some of the
large blocks, e.g., Jackson or org.apache.commons. For your purposes it's
enough to reduce the entire set of dependencies to a box about the same
size as the others. All of the inbound and outbound dependencies would
still be present but they would end at the collapsed dependency.

I need to do a little bit more research but I suspect this is a case that
shows why many of us have moved to other templates. In jinjava (and
thymeleaf?) we can define our own functions. This can dramatically reduce
the amount of cut-and-paste code in the template. Velocity seems to be
limited to macros. This isn't a big problem if you're doing something like
looking up the text color to use based on the maven scope but it makes it
harder to handle some dynamic structural elements. e.g., in dot format the
links can use either a "node" or a "node":port  (note lack of quotes). The
former goes to the overall element while the latter goes to a specific
element in a list/table.

Bear




On Mon, Mar 24, 2025 at 9:38 PM Bear Giles <bgi...@coyotesong.com> wrote:

> One of the benefits (to me) is that it makes mismatches in dependency
> versions stand out.
>
> I've been able to figure out how to rotate the graph yet keep it
> relatively (cough) narrow. There's still a few unwanted empty boxes but it
> now has nested groupIds. If you look carefully at the com.faster.jackson
> you'll notice that there's one subgroup that has a single version but two
> other subgroups with multiple versions. Earlier I could see that these
> dependencies were pulled in from two locations and that's why there was a
> difference. Even if couldn't see the exact reason I know that this larger
> group of dependencies usually have the same version and if not I should
> take a closer look.
>
> At other places I've had to spend some time tracking down unnecessary
> transitive dependencies and fix them with a combination of "optional" and
> exclusions. Something like this would probably be easier to examine than a
> text listing of several hundred lines.
>
> (BTW the scope and 'optional' will be encoded as color and italics,
> respectively.)
>
> The latest version is attached. It's clear that it make sense to move
> "common-*" under the "org.apache.commons" group. I'm not sure about the
> org.google group - doing this kept some dependencies in the same subgraph
> but it also brought in some one-offs.
>
> [image: tree2.png]
>
>
> On Mon, Mar 24, 2025 at 7:37 PM Tomo Suzuki <suzt...@google.com.invalid>
> wrote:
>
>> That’s a beautiful diagram. Would you share the background you wanted to
>> visualize it in that way? Did it get some tasks done?
>>
>> Regards,
>> Tomo
>>
>> On Mon, Mar 24, 2025 at 19:02 Bear Giles <bgi...@coyotesong.com> wrote:
>>
>> > I should be clear - the glitch is the column of empty boxes above the
>> root
>> > dependency. They should not appear.
>> >
>> > The grayed areas, with one exception, have the same groupId. If they
>> also
>> > have the same version then the artifacts will be listed in a single
>> stack.
>> > The 'type' is omitted if it's "jar", otherwise it will be included on
>> that
>> > line.
>> >
>> > If there are multiple versions in the cluster then there will be
>> > multiple "records" with same structure as the standalone dependencies.
>> The
>> > only difference is that they''ll drop the groupId.
>> >
>> > The one exception is the "Database Drivers" in the bottom left - that's
>> an
>> > experiment specific to this pom - sometimes you might have a group
>> > independent dependencies that serve the same role, e.g., database JDBC
>> > drivers. Does it make sense to put them into their own cluster?
>> >
>> > Bear
>> >
>> > On Mon, Mar 24, 2025 at 4:52 PM Bear Giles <bgi...@coyotesong.com>
>> wrote:
>> >
>> >> The maven-dependency-plugin has a '.dot' option but because of the
>> layout
>> >> it's useless for anything other than the most trivial dependency
>> trees.  I
>> >> know we can't replace existing functionality but this could be added as
>> >> "dot2", or a 'variant" property could be added to the mojo.
>> >>
>> >> There are some few obvious tweaks but some of them hit the limitations
>> of
>> >> the graphviz
>> >> library, or at least my understand of it. However I think I have
>> >> something very close to a good alternative to the standard layout - I
>> just
>> >> need to ask the graphviz people as question first.
>> >>
>> >> I've attached a sample pom and the generated png file. This is the pom
>> I
>> >> use for an application that creates a document listing the database
>> >> metadata for multiple databases.
>> >>
>> >> Bear Giles
>> >> [image: tree2.png]
>> >>
>> >
>>
>

Reply via email to