Java multi-project creation with Gradle

How to do multi-project in Gradle.

Create jar file in a single project

Before multi-project, first try creating and running a jar file in a single project.

gradle project creation

gradle initialization


$ gradle init

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 1

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Project name (default: JavaMultiProject): 

> Task :init
Get more help with your project: https://guides.gradle.org/creating-new-gradle-builds

BUILD SUCCESSFUL in 6s
2 actionable tasks: 2 executed

Modify build.gradle file

Modify the automatically created build.gradle file a bit. The important thing is to create the jar task.

build.gradle


apply plugin: 'java'
apply plugin: 'application'

sourceCompatibility = 11
targetCompatibility = 11

repositories {
    jcenter()
}

dependencies {
}

mainClassName = 'App'
jar {
    manifest {
        attributes 'Main-Class': "App"
    }
}

Source creation

Create a source to run.

src/main/java/App.java


public class App {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}

Try build and run.

build and run


$ gradle build

BUILD SUCCESSFUL in 2s
5 actionable tasks: 1 executed, 4 up-to-date

$ java -jar build/libs/JavaMultiProject.jar 
Hello

You have successfully created and run the jar file in a single project.

Creating a multi-project

Now let's create a multi-project.

This is the directory structure.

Constitution


.(JavaMultiProject)
├── bar  (Application project)
│   ├── src
│   ├── build.gradle
├── foo  (Application project)
│   ├── src
│   ├── build.gradle
├── share  (Project to be used as a common library)
│   ├── src
│   ├── build.gradle
├── build.gradle
├── setting.gradle

Create a directory.

python


$ mkdir -p bar/src/main/java
$ mkdir -p foo/src/main/java
$ mkdir -p share/src/main/java

Fixed setting.gralde

If you want to make a multi-project, set it in setting.gradle.

Specify the subproject in include.

setting.gradle


rootProject.name = 'JavaMultiProject'
include 'foo', 'bar', 'share'

This makes each for`` bar share directory recognized as a subproject. IntelliJ IDEA also recognizes the project in this way.

browser.png

Fix build.gradle

In build.gradle that exists in the project root, specify the settings that apply to all subprojects by specifying subprojects.

build.gradle(root)


allprojects {
}

subprojects {
    apply plugin: 'java'

    sourceCompatibility = 11
    targetCompatibility = 11

    repositories {
        jcenter()
    }
}

Next is the subproject build.gradle. Let's start with the application project bar.

bar/build.gradle


apply plugin: 'application'

dependencies {
    implementation project(":share")
}

mainClassName = 'com.example.Bar'
jar {
    manifest {
        attributes 'Main-Class': "com.example.Bar"
    }
    from configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}

To explain the important part, The ʻimplementation project (": share") `in dependencies defines that it depends on another subproject, share.

I also specified from ~ in the jar task, which means that the dependent libraries are included in the jar of the Bar project.

By the way, if the from method does not exist, the NoClassDefFoundError error will be output because the dependent library is not included in the jar. Just in case I got stuck with this.

python


$ java -jar bar/build/libs/bar.jar 
Exception in thread "main" java.lang.NoClassDefFoundError: com/example/Hello
	at com.example.Bar.main(Bar.java:5)
Caused by: java.lang.ClassNotFoundException: com.example.Hello
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	... 1 more

The foo project is almost the same as the bar project, but I'll mention it just in case. Only mainClassName is changed to Foo.

foo/build.gradle


apply plugin: 'application'

dependencies {
    implementation project(":share")
}

mainClassName = 'com.example.Foo'
jar {
    manifest {
        attributes 'Main-Class': "com.example.Foo"
    }
    from configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}

share's build.gradle doesn't mention anything this time.

share/build.gradle


code

Finally, I will write the code.

bar/src/main/java/com/exmaple/Bar.java


package com.example;

public class Bar {
    public static void main(String[] args) {
        var hello = new Hello("Bar");
        System.out.println(hello.say());
    }
}

foo/src/main/java/com/exmaple/Foo.java


package com.example;

public class Foo {
    public static void main(String[] args) {
        var hello = new Hello("Foo");
        System.out.println(hello.say());
    }
}

share/src/main/java/com/exmaple/Hello.java


package com.example;

public class Hello {
    private final String name;
    public Hello(String name) {
        this.name = name;
    }

    public String say() {
        return name + " Hello!";
    }
}

build and run

I will try to build. Subproject tasks are executed with : (project name): (task name).

Also, the build of the share project on which bar depends will be executed at the same time.

python


$ gradle :bar:build

BUILD SUCCESSFUL in 804ms
7 actionable tasks: 7 up-to-date

$ ls -l bar/build/libs/
total 8
-rw-r--r--  1 ysaito  staff  1591  4 29 21:15 bar.jar

If you unzip the created jar for reference, you can see that Hello.class inside the share is included in the created bar.jar.

Unzip the jar and check


$ jar xvf bar.jar 
  META-INF/Was created
 META-INF/MANIFEST.MF was deployed
  com/Was created
  com/example/Was created
 com/example/Bar.class has been expanded
 com/example/Hello.class has been expanded

Now that the jar is created, let's run it.

python


$ java -jar bar/build/libs/bar.jar 
Bar Hello!
$ java -jar foo/build/libs/foo.jar 
Foo Hello!

reference

Gradle User Guide-> Build Multi-Project

Recommended Posts

Java multi-project creation with Gradle
Build a Java project with Gradle
Multi-project with Keycloak
[Java] Create an executable module with Gradle
CICS-Run Java applications-(3) Build management with Gradle
java file creation
Configure a multi-project with subdirectories in Gradle
Java automated test implementation with JUnit 5 + Gradle
java directory creation
Make SpringBoot1.5 + Gradle4.4 + Java8 + Docker environment compatible with Java11
Static code analysis with Checkstyle in Java + Gradle
Build and test Java + Gradle applications with Wercker
Using Gradle with VS Code, build Java → run
I wanted to gradle spring boot with multi-project
[Jakarta EE 8 application development with Gradle] 2. Project creation
Install java with Homebrew
Use ProGuard with Gradle
Integration Test with Gradle
Eclipse ~ Java project creation ~
Change seats with java
Install Java with Ansible
CLI creation with thor
Comfortable download with JAVA
First gradle build (Java)
Install Gradle with ubuntu16.04
Graph creation with JFreeChart
Switch java with direnv
DataNucleus starting with Gradle
Download Java with Ansible
Let's scrape with Java! !!
Use WebJars with Gradle
Build Java with Wercker
Get started with Gradle
Use jlink with gradle
Java Discord Bot creation
[Java] Calculator program creation 1
Endian conversion with JAVA
Check coverage with Codecov in Java + Gradle + Wercker configuration
Easy BDD with (Java) Spectrum?
Use Lambda Layers with Java
Getting Started with Java Collection
Gradle + Kotlin-Generate jar with DSL
Java Config with Spring MVC
Basic Authentication with Java 11 HttpClient
Let's experiment with Java inlining
Run batch with docker-compose with Java batch
[Template] MySQL connection with Java
Rewrite Java try-catch with Optional
Install Java 7 with Homebrew (cask)
[Java] JSON communication with jackson
Java to play with Function
Try DB connection with Java
Spring + Gradle + Java Quick Start
[Gradle] About Java plug-in tasks
Enable Java EE with NetBeans 9
[Java] Creation of original annotation
[Java] JavaConfig with Static InnerClass
Try gRPC with Java, Maven
Let's operate Excel with Java! !!
Version control Java with SDKMAN
Spring Boot 2 multi-project in Gradle