DEV Community

khalil la
khalil la

Posted on • Edited on

Announcing @jnxplus/nx-gradle

I like to use Nx workspace to manage my projects. I don't put all my projects in one workspace but I use one workspace per multi-module project.
It works nicely with node frameworks like angular, react, nest... But when its come to other languages and frameworks, we need to use custom plugins.

In this article I will use my plugin @jnxplus/nx-gradle to add support of spring boot and Gradle multi-project builds to Nx workspace.

@jnxplus/nx-gradle add to the Spring Boot world, an opinionated way to integrate Spring Boot apps/libs inside Nx workspace using Gradle multi-project builds.

Let's show you how to use it.

We start by creating a workspace :
Open a terminal and run this command to create a new workspace :

npx create-nx-workspace@latest
Enter fullscreen mode Exit fullscreen mode

When asked provide my-org as name and choose an empty workspace :

devs> npx create-nx-workspace@latest
npx: installed 48 in 3.278s
√ Workspace name (e.g., org name)     · my-org
√ What to create in the new workspace · empty
√ Use Nx Cloud? (It's free and doesn't require registration.) · No

>  NX  Nx is creating your workspace.
Enter fullscreen mode Exit fullscreen mode

Now and in the same terminal go inside my-org folder :

cd my-org 
Enter fullscreen mode Exit fullscreen mode

1. Install the plugin

In the workspace root run this command to install the plugin :

npm install --save-dev @jnxplus/nx-gradle
Enter fullscreen mode Exit fullscreen mode

2. Add Spring boot and Gradle wrapper support

The following command adds Spring boot and Gradle support (Gradle wrapper and config files) to the workspace. This only needs to be performed once per workspace.

nx generate @jnxplus/nx-gradle:init
Enter fullscreen mode Exit fullscreen mode

I choose the version of Java supported by my operating system and the default value for Gradle root project:

my-org> nx generate @jnxplus/nx-gradle:init
√ Which version of Java would you like to use? · 11
√ What rootProjectName would you like to use? · boot-multiproject
CREATE checkstyle.xml
CREATE gradle/wrapper/gradle-wrapper.jar
CREATE gradle/wrapper/gradle-wrapper.properties
CREATE gradle.properties
CREATE gradlew
CREATE gradlew.bat
CREATE settings.gradle
UPDATE nx.json
UPDATE .gitignore 
Enter fullscreen mode Exit fullscreen mode

As you see, the command added the following files :

  • checkstyle.xml for linting.
  • Gradle wrapper and Gradle executables for windows and Linux : Using Gradle Wrapper we can distribute/share a project to everybody to use the same version and Gradle's functionality(compile, build, install...) even if it has not been installed
  • gradle.properties : This file contain Java, Spring Boot and dependency management versions that we will use for all apps and libs inside Nx worspace.
  • settings.gradle : Here we will add our apps and libs later so Gradle will be able to perform its tasks.

We also updated nx.json file to add the plugin for dep-graph feature and .gitignore so we can ignore Gradle build and cache folders.

3. Usage

Generate an application

nx generate @jnxplus/nx-gradle:application my-app
Enter fullscreen mode Exit fullscreen mode

When asked, provide answers or choose default :

my-org> nx generate @jnxplus/nx-gradle:application my-app
√ What groupId would you like to use? · com.example
√ What version would you like to use? · 0.0.1-SNAPSHOT
√ Which packaging would you like to use? · jar
UPDATE workspace.json
UPDATE nx.json
CREATE apps/my-app/build.gradle
CREATE apps/my-app/src/main/java/com/example/myapp/HelloController.java
CREATE apps/my-app/src/main/java/com/example/myapp/MyAppApplication.java
CREATE apps/my-app/src/main/resources/application.properties
CREATE apps/my-app/src/test/java/com/example/myapp/HelloControllerTests.java
CREATE apps/my-app/src/test/resources/application.properties
UPDATE settings.gradle
Enter fullscreen mode Exit fullscreen mode

Check the settings.gradle, here we added a entry for my-app :

rootProject.name = 'boot-multiproject'
include('apps:my-app')
Enter fullscreen mode Exit fullscreen mode

Build the app

nx build my-app
Enter fullscreen mode Exit fullscreen mode

If you look carefully to the console, you will see that we run the command :

Executing command: gradlew.bat :apps:my-app:bootJar 
Enter fullscreen mode Exit fullscreen mode

Since we choose a jar packaging, we run this command.
For war packaging, we run bootWar.

Serve the app

nx serve my-app
Enter fullscreen mode Exit fullscreen mode

Here under the hood we run the command : bootRun.
Open http://localhost:8080 to see app working:

Alt Text

Test the app
To test the app run this command :

nx test my-app
Enter fullscreen mode Exit fullscreen mode

Alt Text

What I like to do to see if test command is really working is breaking a test, and run it again :

So change the test and add a comma between Hello and World :

@Test
public void shouldReturnHelloWorld() throws Exception {
  this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
                .andExpect(content().string(containsString("Hello, World")));
}
Enter fullscreen mode Exit fullscreen mode

Now rerun the same command :
Alt Text
Perfect, now the test target is failing.
Revert change and let's generate this time a library.
To generate a library use this command :

nx generate @jnxplus/nx-gradle:library my-lib
Enter fullscreen mode Exit fullscreen mode

When asked, provide answers or choose default :

my-org> nx generate @jnxplus/nx-gradle:library my-lib
√ What groupId would you like to use? · com.example
√ What version would you like to use? · 0.0.1-SNAPSHOT
UPDATE workspace.json
UPDATE nx.json
CREATE libs/my-lib/build.gradle
CREATE libs/my-lib/src/main/java/com/example/mylib/HelloService.java
CREATE libs/my-lib/src/test/java/com/example/mylib/HelloServiceTests.java
CREATE libs/my-lib/src/test/java/com/example/mylib/TestConfiguration.java
UPDATE settings.gradle
Enter fullscreen mode Exit fullscreen mode

Check the settings.gradle, here we added a entry for my-lib :

rootProject.name = 'boot-multiproject'
include('libs:my-lib')
include('apps:my-app')
Enter fullscreen mode Exit fullscreen mode

Like an app, we can build it and test it :
Build :

nx build my-lib 
Enter fullscreen mode Exit fullscreen mode

Test :

nx test my-lib 
Enter fullscreen mode Exit fullscreen mode

But we can't run it with serve target :

my-org> nx serve my-lib
>  NX   ERROR  Cannot find target 'serve' for project 'my-lib'
Enter fullscreen mode Exit fullscreen mode

Hope you like this article, and give this plugin a try :)

You can find the Github code here :
https://github.com/khalilou88/my-org

Top comments (2)

Collapse
 
joelbonetr profile image
JoelBonetR 🥇

Thank you!
That's quite useful, the stack Java + JS is pretty common and monorepos are getting more attention as the time goes on 😁

Collapse
 
gad2103 profile image
gabriel duncan

that github url is 404. would you mind making it public again? thanks for the interesting article!