Programmatically retrieve Maven dependency graph - java

Given a Maven artifact (groupId:artifactId:version), how can I programmatically query its dependencies? (I don't need actually retrieve any artifacts, just the dependency information.)
Edit to add I'd like to do this outside of a Maven plug-in, and I'd like to build up a dependency graph.

If you're using a maven plugin (ie: extend AbstractMojo), you can do the following:
/**
* #parameter expression="${project}"
*/
private org.apache.maven.project.MavenProject mavenProject;
List<org.apache.maven.model.Dependency> depmgtdeps = mavenProject.getDependencyManagement().getDependencies();
That will give you the actual dependency objects that it detects. The MavenProject class has a bunch of other methods as well for reading various pom related things. However, I don't believe this works outside a plugin, or at least, I've never tried to do it.

I found these two links helpful..
A Maven Plugin for retrieving the dependencies
Using Eclipse Plugin

The following groovy script uses ivy to resolve dependencies
import groovy.xml.NamespaceBuilder
// Main program
// ============
def ant = new AntBuilder()
def ivy = NamespaceBuilder.newInstance(ant, "antlib:org.apache.ivy.ant")
ivy.resolve(
inline:true,
keep:true,
conf:"default",
organisation:"org.springframework",
module:"spring-core",
revision:"3.1.1.RELEASE",
)
ivy.report(toDir:"reports")
Generates a HTML report and a graphml file:
|-- report.groovy
|-- reports
| |-- ivy-report.css
| |-- org.springframework-spring-core-caller-default.graphml
| `-- org.springframework-spring-core-caller-default.html

Related

IntelliJ / Gradle - composite build project - how to import from different module?

I'm new to Java and am currently trying to build a cucumber / selenium project in IntelliJ that contains two modules: A library project containing page definitions, and a test project that contains the cucumber features and step definitions that talk to those page definitions. The idea is that the page definitions are a shared resource, and the tests are specific to different projects / groups. Both modules are at the same level underneath the parent project. The build is using Gradle, and the settings.gradle file for the parent looks as follows:
rootProject.name = 'composite-builds'
includeBuild 'libraryproject'
includeBuild 'testproject'
Using Gradle includeBuild on the parent project works fine and the whole project imports. However I am having no luck using the library project in my import statements in the test project. It consistently returns me these kinds of error: java: package libraryproject.pageFactory.examplePages does not exist and is clearly not seeing the library module.
What do I need to do / add in order for the test project to recognise the library project? I did try to also add the includeBuild statement in the settings.gradle for the test project but this made no difference.
The library can be found here
Update: the real reason that I cannot see the modules from the library project is that they were held in the test folder, not main.
Go to your build.gradle file
Instead of includeBuild use dependencies{compile{project(':libraryproject')}}
Inside the Root Project of libraryproject which is in your case the composite-builds. Change includeBuild to include in the settings.gradle
rootProject.name = 'composite-builds'
include ':libraryproject'
include ':testproject'
If it is in the same root:
dependencies {
compile(
project(':libraryproject')
)
}
Subfolder:
dependencies {
compile(
project(':myFolder1:myFolder2:libraryproject')
)
}

Java 9 - Cannot be resolved as a module

Very simple use case, I am using Eclipse Oxygen 4.7.3a that includes support from Java 9. I have two projects that are Java 9 projects:
- projectOne
| - src
| - module-info.java
| - com
| - package1
| - first
| Classificator.java
- projectTwo
| - src
| - module-info.java
| - com
| - package2
| - second
| Classifiable.java
I want to use the Classifiable class inside the Classificator, so I try to import the second module into the first project.
module-info.java Project 1:
module projectOne {
requires projectTwo;
}
module-info.java Project 2:
module projectTwo {
}
Eclipse is giving me the error:
projectTwo cannot be resolved to a module
Do I have to gather all my Java projects under one "main project" in order to let Eclipse know that all those modules are usable inside it? Or have I missed something else?
No, you don't need them to be in the same directory. Ideally, your project-one module defines some uses, which are implements by your project-two module (or vice-versa). Get the runtime implementation of your used interfaces. For this, both jars/classes must be on the module path.
For further information on module build, multi module builds,... you can refer to this link. Even if you do not use gradle, its tutorial on java 9 module build is quite interesting and gives some insight.
While wiring as a service is certainly a viable approach (as described in the other answer), let me add that requires can be made to work, too, of course.
The thing that was probably missing from the first approach is: Eclipse still needs to know where to look for modules. In real world projects this will typically be mediated by your build tool of choice plus a plug-in like m2e or buildship.
If no such plug-in is used, a normal project dependency should be added to the Build Path of project projectOne in order to make project projectTwo visible. Once the project is on the Build Path the module defined by the project can be resolved in references in module-info.java.

Building with Intellij 2017.2 /out directory duplicates files in /build directory

After updating to Intellij 2017.2, building my project creates an /out directory that contains generated source files and resource files. These files duplicate files that are already contained in /build and result in duplicate class compiler errors for the generated classes. Any ideas on a fix I need in Gradle or IntelliJ?
IntelliJ IDEA is no longer sharing the output with Gradle, please see this ticket for details.
You can either override it via the following configuration:
allprojects {
apply plugin: 'idea'
idea {
module {
outputDir file('build/classes/main')
testOutputDir file('build/classes/test')
}
}
if(project.convention.findPlugin(JavaPluginConvention)) {
// Change the output directory for the main and test source sets back to the old path
sourceSets.main.output.classesDir = new File(buildDir, "classes/main")
sourceSets.test.output.classesDir = new File(buildDir, "classes/test")
}
}
or delegate the build to Gradle: File | Settings | Build, Execution, Deployment | Build Tools | Gradle | Runner => Delegate IDE build/run actions to gradle.
File | Project Structure | Project Settings | Modules | Paths tab | Compiler output
Select 'Inherit project compile output path' to continue using /build for build artifacts
Here is my understanding:
Basically, this is a work-around for an incompatibility issue between
Gradle build path and IDEA output path.
the issue is - https://github.com/gradle/gradle/issues/2315
the solution is - keep these two directories seperate, therefore you have two (out/ and build/) https://youtrack.jetbrains.com/issue/IDEA-189063

Play Framework 2.2 subprojects

I'm trying to add a subproject to my Play Framework project, and find the docs generally lacking there.
I've created a play project, let's call it my-web, and it's in directory /my-cool-project/web. I also have another project I would like my-web to depend on, let's call it my-model. my-model a git submodule for my-cool-project, and when I pull it, my directory structure is
/my-cool-project
/my-web
/app
/conf
build.sbt
/my-model
/main
/java
/src
Now, how do I add my-model as a subproject for my-web? I've tried
lazy val myModel = project.in(file("../my-model"))
but all I get is that my-model is not contained within the build root of my-web... Anything else I can try in build.sbt?
project is used to define the project model and sub-projects. For sibling project, you can use RootProject or ProjectRef. In your case, I would use RootProject.
lazy val myModel = RootProject(file("../my-model"))
When you compile a project, compilation on all RootProjects and ProjectRefs will triggered as well. You will define your project setting for my-model inside the build file in my-model project. This reduce the duplication for the project definition.
Think about RootProject and ProjectRef like project reference in Eclipse.
Let me know if this is what you are looking for.
change lazy val myModel = project.in(file("../my-model"))
to
lazy val myModel = project.in(file("my-model"))
Path it refers is from root of the project. So, you can give this path accordingly.

Java code to convert a list of dependencies into a build order?

Given I have a list of dependencies available as bits in external files. These will be aggregated into a list like:
module1
module2 dependsOn module1
module3 dependsOn module1
module4 dependsOn module3
I would like to create a build order where each build step is found on one line, and each line contains a list of one or more modules which can be compiled at the same time, and which only depend on modules compiled earlier.
So, for the above data set, create a list like:
module1
module2,module3
module4
Now, this is basically just a problem of creating a directed graph, and analyzing it. Now, I am using Ant, and would very much like to use something off-the-shelf... what is the minimum of custom code I need to have it create such a dependency-aware build list starting from the given input? I do not want to write all code myself (which I know how to do), but looking for libraries to help me here...
BTW, these modules are actually custom modules, so maven will not work. Moreover, the module list is created on the fly from the Java source code, and I cannot hard code this in the build file.
You can use topological sorting to see how the real ordering is. This can be done by using unix util tsort or you can search for an implementation for toplogical sort (Excalibur Framework has something like this).
Ant can handle that for you. You basically describe your module dependencies as target dependencies.
Have a look at [http://stroy.wikidot.com/motpe]. It is 2 ant scripts with same conventions
to handles multi module builds.
Draw a tree of your dependencies and look at the levels. You can start building at the root and build each level of the tree in parallel given that the levels above are already built.
1----->2
|
----->3----->4
^ ^ ^
| | |
A B C
Build A first (module 1), then B (2&3), then C (4).
EDIT:
If you are using Ant and are asking specifically for a dependency resolution solution for Ant, you could take a look at Apache Ivy

Categories

Resources