Author Archives: oleg

Dependency Resolution as a Diagram


December 11, 2008 By oleg

They say that one picture is worth a thousand words, so I shut up:

What is Mercury?


November 24, 2008 By oleg

Mercury is a serious attempt to:

  • Decouple major Maven components, making them available as stand-alone building blocks rather then having Maven as as one big monolith, not usable outside of its environment.
  • Artifact – clearly separate an Artifact from its metadata.
  • Repository – convert a repository into active component. It used to give back just pathOf(), now it accepts GAV collections and gives back either metadata or full blown Artifacts.
  • Transport – an API in development.
  • DependencyTreeBuilder main API for dependency graph creation and conflict resolution.
  • Decouple container, so that these components are just plain pojos.
  • Introduce Jetty-based HTTP/HTTPS and WebDAV transactional transport layer.
  • Asynchronous downloads and uploads. One of the few successful usages of Java NIO in OSS.
  • Transactional operations – all-or-nothing for file sets.
  • Move integrity control into transport layer, upper level components should not care about these details.
  • Abstract out metadata cache, provide at least one implementation there.
  • Integrate these changes back to Maven 3.x to make it even better platform than it is right now (if it is possible to be better :) )

Currently Mercury can already be used for accessing repositories, and conflict resolution is under testing.

Mercury event framework design notes


November 21, 2008 By oleg

For a long time I’ve been perplexed by what is going inside Maven, what’s there under the hood. Later I started learning the code and it gave me some perspective. Then I wrote a chunk of code – Mercury, but the exact understanding of what is happening inside is still hard to grasp: the code base is rather big and logic rather complex for a human mind to follow all the details.

All that, plus the necessity to provide tool integration, led to the idea to introduce an event framework into Mercury. All major processing object implement EventGenerator interface, that allows client code to register MercuryEventListener implementations and unRegister them as well. Continue reading

Mercury – externalized dependencies


October 21, 2008 By oleg

Inspiration

In Mercury we made an attempt to bring some contemporary ideas into Maven, make Maven not a monolithic build system, but rather a lego-like construction set that allows users to create systems they need. One set of building blocks in particular – implementation of the idea that dependencies is a universal commodity, that exists outside of Maven world. And operation of resolving conflicts on those dependencies can apply to a broader range of dependencies, not just <dependencies/> tag in the POM file.

For example – it should be relatively easy to plug in an implementation to read OSGi bundle dependencies. Or read a .properties file with dependencies.

Or – my favorite – keep dependencies in a Drools-backed DSL file. I will try to create this implementation after we integrate Maven POM dependency reader into Mercury.

How is it done:

  • Dependency trees and manipulated by DependencyTreeBuilder object
  • DependencyTreeBuilder instance is created out of a collection of Repositories (to find Artifacts) and and instance of DependencyProcessor.
  • DependencyProcessor abstraction is that externalization component for reading/processing depedencies, making the builder independent of actual dependency information storage

Example code

1
2
3
4
5
6
    DependencyTreeBuilder dtb
        = new DependencyTreeBuilder( null, null, null, reps, processor );
    MetadataTreeNode root
        = dtb.buildTree( new ArtifactBasicMetadata( "org.apache.maven:maven-core:2.0.9" ) );
    List cp
        = dtb.resolveConflicts( ArtifactScopeEnum.compile );

This example demonstrates full dependency resolution cycle:

  • full tree is created in root variable
  • compile classpath is stored in variable cp.

The two initialization steps required:

  • create a collection of repositories in reps
  • get an instance of DependencyProcessor into processor

Also interesting – resulting classpath is a list of artifact metadata objects, not artifact binaries. So in order to actually bring the binaries to local machine, we’ll need one more call – to VirtualRepositoryReader, which I will describe it in a separate posting.

What’s important here is the fact that operation of fetching binaries from remote repositories is separated from building dependency tree as well as from resolving conflicts. Which means that you can call all of those operations independently to construct a workflow you need for a particular application. All the metadata that was fetched in the process of creating dependency tree is cached by a RepositoryMetadataCache component, that complies with repository update policy.