Announcing @jnxplus/nx-gradle
Tags: nx, springboot, gradle
Published: 2021-09-12 12:01:09

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 :
```bash
npx create-nx-workspace@latest
```
When asked provide my-org as name and choose an empty workspace :
```bash
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.
```

Now and in the same terminal go inside my-org folder :
```bash
cd my-org 
 ```
### 1. Install the plugin

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

```bash
npm install --save-dev @jnxplus/nx-gradle
```
### 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.

```bash
nx generate @jnxplus/nx-gradle:init
```
I choose the version of Java supported by my operating system and the default value for Gradle root project:
```bash
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 
```
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
```bash
nx generate @jnxplus/nx-gradle:application my-app
```
When asked, provide answers or choose default :
```bash
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
```

Check the `settings.gradle`, here we added a entry for my-app :
```bash
rootProject.name = 'boot-multiproject'
include('apps:my-app')
```

Build the app
```bash
nx build my-app
```
If you look carefully to the console, you will see that we run the command :
```bash
Executing command: gradlew.bat :apps:my-app:bootJar 
```
Since we choose a `jar` packaging, we run this command.
For war packaging, we run `bootWar`.

Serve the app
```bash
nx serve my-app
```
Here under the hood we run the command : `bootRun`.
Open http://localhost:8080 to see app working:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zxhxo65wmsoq3m8sjppm.PNG)

Test the app
To test the app run this command :
```bash
nx test my-app
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nr1g48yrse7qqpe2z4k0.PNG
)

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 :

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

Now rerun the same command :
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/08kf1id8zzdap3sekus9.PNG)
Perfect, now the test target is failing.
Revert change and let's generate this time a library.
To generate a library use this command :
```bash      
nx generate @jnxplus/nx-gradle:library my-lib
```
When asked, provide answers or choose default :
```bash
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
```
Check the `settings.gradle`, here we added a entry for my-lib :
```bash
rootProject.name = 'boot-multiproject'
include('libs:my-lib')
include('apps:my-app')
```
Like an app, we can build it and test it :
Build : 
```bash
nx build my-lib 
```                                    
Test : 
```bash       
nx test my-lib 
```
But we can't run it with serve target :
```bash 
my-org> nx serve my-lib
>  NX   ERROR  Cannot find target 'serve' for project 'my-lib'
```

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

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