1

I have a root project with multiple subprojects. Initially, we've kept the projects as separate Maven projects but I've realized Gradle is much more suitable for me to use. But for one of the subprojects we'd rather not convert it to a Gradle project, but keep it as a Maven project.

So I've tried to keep a Maven project as a subproject to a Gradle project, but building fails because the dependencies listed in the Maven projects pom.xml are not included. Below is my experiment

Folder/project structure

root (gradle root project)
|- api (maven project)
|- project (gradle subproject, depends on the "api" project)

root/settings.gradle

rootProject.name = 'root'

def subDirs = rootDir.listFiles(new FileFilter() {
    public boolean accept(File file) {
        if (!file.isDirectory()) {
            return false
        }
        if (file.name == 'buildSrc') {
            return false
        }
        return new File(file, 'build.gradle').isFile()
    }
});

subDirs.each { File dir ->
    include dir.name
}

root/build.gradle

import org.gradle.api.artifacts.*

apply plugin: 'base' // To add "clean" task to the root project.

subprojects {
    apply from: rootProject.file('common.gradle')
}

task mergedJavadoc(type: Javadoc, description: 'Creates Javadoc from all the projects.') {
    title = 'All modules'
    destinationDir = new File(project.buildDir, 'merged-javadoc')

    // Note: The closures below are executed lazily.
    source {
       subprojects*.sourceSets*.main*.allSource
    }
    classpath.from {
        subprojects*.configurations*.compile*.copyRecursive({ !(it instanceof ProjectDependency); })*.resolve()
    }
}

root/common.gradle

//
// This file is to be applied to every subproject.
//

apply plugin: 'java'
apply plugin: 'maven'

String mavenGroupId = 'com.mycompany.myproject'
String mavenVersion = '1.0-SNAPSHOT'

sourceCompatibility = '1.8'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

repositories {
    mavenCentral();
    // You may define additional repositories, or even remove "mavenCentral()".
    // Read more about repositories here:
    //   http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:repositories
}

dependencies {
    // Adding dependencies here will add the dependencies to each subproject.
    testCompile group: 'junit', name: 'junit', version: '4.10'
}

String mavenArtifactId = name

group = mavenGroupId
version = mavenVersion

task sourcesJar(type: Jar, dependsOn: classes, description: 'Creates a jar from the source files.') {
    classifier = 'sources'
    from sourceSets.main.allSource
}

artifacts {
    archives jar
    archives sourcesJar
}

configure(install.repositories.mavenInstaller) {
    pom.project {
        groupId = mavenGroupId
        artifactId = mavenArtifactId
        version = mavenVersion
    }
}

task createFolders(description: 'Creates the source folders if they do not exist.') doLast {
    sourceSets*.allSource*.srcDirs*.each { File srcDir ->
        if (!srcDir.isDirectory()) {
            println "Creating source folder: ${srcDir}"
            srcDir.mkdirs()
        }
    }
}

root/api/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany.myproject</groupId>
    <artifactId>api</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/de.dev-eth0.dummycreator/dummy-creator -->
        <dependency>
            <groupId>de.dev-eth0.dummycreator</groupId>
            <artifactId>dummy-creator</artifactId>
            <version>1.3</version>
        </dependency>
    </dependencies>
</project>

root/project/build.gradle

if (!hasProperty('mainClass')) {
    ext.mainClass = 'com.mycompany.myproject.HelloWorld'
}

dependencies {
    compile project(":api")
}

root/api/src/main/java/com/mycompany/myproject/api/Api.java

package com.mycompany.myproject.api;

import org.dummycreator.DummyCreator;

public class Api {

    public static void sayHello() {
        System.out.println("Hello from API!");

        DummyCreator dc = new DummyCreator();
        Integer integer = dc.create(Integer.class);

        System.out.println("Integer: " + integer);
    }
}

When building "project", I get the following output:

Executing: gradle build
Arguments: [-c, C:\Users\birger\Desktop\test\root\settings.gradle]

C:\Users\birger\Desktop\test\root\api\src\main\java\com\mycompany\myproject\api\Api.java:3: error: package org.dummycreator does not exist
import org.dummycreator.DummyCreator;
                       ^
C:\Users\birger\Desktop\test\root\api\src\main\java\com\mycompany\myproject\api\Api.java:10: error: cannot find symbol
        DummyCreator dc = new DummyCreator();
        ^
  symbol:   class DummyCreator
  location: class Api
C:\Users\birger\Desktop\test\root\api\src\main\java\com\mycompany\myproject\api\Api.java:10: error: cannot find symbol
        DummyCreator dc = new DummyCreator();
                              ^
  symbol:   class DummyCreator
  location: class Api
3 errors
:api:compileJava FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':api:compileJava'.
> Compilation failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 0.106 secs



Build failure (see the Notifications window for stacktrace): gradle build

So, what's the easiest way to make the Maven subproject "build as normal", as a subproject of the Gradle root project, without actually having to convert it to a Gradle project?

birgersp
  • 3,909
  • 8
  • 39
  • 79
  • This might help, though it doesn't look like it's actively maintained: https://github.com/uklance/gradle-maven-share (Taken from here: https://stackoverflow.com/questions/40352951/include-gradle-module-to-maven-project ) – Vivek Chavda Aug 15 '17 at 13:42
  • 1
    I recommend to migrate the maven project to Gradle...and that's it...What is the problem here? – khmarbaise Aug 15 '17 at 14:18
  • 1
    Why do you want to do such a thing :( ? – LazerBanana Aug 15 '17 at 14:37
  • Migrating the Maven project to Gradle is not an option. Then I'd be better off building the Maven project separately and keeping it as an "external" dependency in the other projects. – birgersp Aug 16 '17 at 06:48
  • fyi: the dummycreator project has reincarnated as [lorem-ipsum-objects](https://github.com/bbottema/lorem-ipsum-objects), which solved some bugs. – Benny Bottema Nov 02 '19 at 21:26

1 Answers1

0

If you called mvn install on the maven project, you could then use

repositories { 
    mavenLocal()
}

in the gradle project to depend on the jar via group/artifact/version. With gradle's maven dependency integration you would then get all of the transitive dependencies from the pom

lance-java
  • 25,497
  • 4
  • 59
  • 101
  • I ended up invoking `mvn install` on the Maven project as a step build process of the root project. – birgersp Aug 17 '17 at 12:34
  • If you were clever, you could configure `src/main/java`, `src/main/resources` and `pom.xml` as the [task inputs](https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/TaskInputs.html) and configure the `jar` and `pom` files under the maven local directory as the [task outputs](https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/TaskOutputs.html) then gradle would only need to invoke maven when the sources or `pom.xml` change – lance-java Aug 17 '17 at 12:57