[JAVA] Add module with Spring Boot

Thing you want to do

reference

Getting Started · Creating a Multi Module Project

environment

procedure

Preparation of hello module

setting.gradle


rootProject.name = 'demo'
include 'hello'

Prepare build.gradle for hello module

Create build.gradle directly under the hello directory and write as follows

build.gralde


buildscript {
    ext {
        kotlinVersion = '1.3.10'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
    }
}

ext {
    springBootVersion = '2.1.0.RELEASE'
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'io.spring.dependency-management'

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

compileKotlin {
    kotlinOptions {
        freeCompilerArgs = ["-Xjsr305=strict"]
        jvmTarget = "1.8"
    }
}
compileTestKotlin {
    kotlinOptions {
        freeCompilerArgs = ["-Xjsr305=strict"]
        jvmTarget = "1.8"
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-web')
    implementation('com.fasterxml.jackson.module:jackson-module-kotlin')
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    testImplementation('org.springframework.boot:spring-boot-starter-test')
}

dependencyManagement {
    imports {
        mavenBom("org.springframework.boot:spring-boot-dependencies:${springBootVersion}")
    }
}

You don't need to use ʻorg.springframework.boot's gradle plugin for submodules, but you need spring-boot-dependencies, so use dependency-managementandmavenBom`

Maybe Kotlin plugins should also use dependency-management and mavenBom

Add hello module dependency directly under project

Added the description of ʻimplementation project (': hello')` to the dependencies of build.gradle directly under the project.


...

dependencies {
	implementation('org.springframework.boot:spring-boot-starter-web')
	implementation('com.fasterxml.jackson.module:jackson-module-kotlin')
	implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
	implementation("org.jetbrains.kotlin:kotlin-reflect")
	
	implementation project(':hello')
	
	testImplementation('org.springframework.boot:spring-boot-starter-test')
}

Prepare Controller in hello module

package com.example.demo.hello

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

@RestController
class Controller {

    @GetMapping("/hello")
    fun hello(
        @RequestParam(required = false, defaultValue = "world") name: String
    ): String {
        return "hello $name"
    }
}

Operation check

Points to note when writing unit tests below modules

If you want to write a test using Spring function like using mockMvc in a module, you need to prepare a class with @SpringBootApplication.

Sample unit test using Spring function


@ExtendWith(SpringExtension::class)
@WebMvcTest
class ControllerTest(@Autowired val mockMvc: MockMvc) {
    @Test
    fun test() {
        // /Request parameter name to hello=If you request with test
        //The status is 200 and the response is"hello test"Confirm that
        val request = MockMvcRequestBuilders.get("/hello")
            .param("name", "test")
        mockMvc.perform(request)
            .andExpect(MockMvcResultMatchers.status().isOk)
            .andExpect(MockMvcResultMatchers.content().string("hello test"))
    }

    @SpringBootApplication
    internal class TestConfiguration
}

If you do not prepare a class with @SpringBootApplication, you will get this error message

java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test

The class with @SpringBootApplication may be prepared as a separate file.

About application.properties (yml)

There is such a description in Official Tutorial linked for reference.

In the sample above we have configured the service.message for the test using the default attribute of the @SpringBootTest annotation. It is not advisable to put application.properties in a library because there might be a clash at runtime in the application that uses it (only one application.properties is ever loaded from the classpath). You could put application.properties in the test classpath, but not include it in the jar, for instance by placing it in src/test/resources.

It is not recommended to create application.properties (yml) under each module because it conflicts.

As a test, I prepared application.properties (yml) in the project root and in the hello module in this example and tried to see how it works.

Preparation

Prepare an entry point to display the value of application.properties (yml) in Controller

@RestController
class Controller {

    @Value("\${hoge}")
    private val hoge: String? = null

    @Value("\${fuga}")
    private val fuga: String? = null

...

    @GetMapping("/test")
    fun test(): String {
        return "$hoge $fuga"
    }
}

Verification 1 Prepare application.properties (yml) only in hello module

hoge: hogehoge
fuga: fugafuga

When I ran the application in this state and accessed http: // localhost: 8080 / test, hogehoge fugafuga was displayed.

It works fine even if there is application.properties (yml) only in the module

Verification 2 Prepare application.properties (yml) for both

In the project root


hoge: hoge
fuga: fuga

In the hello module


hoge: hogehoge
fuga: fugafuga

When I ran the application in this state and accessed http: // localhost: 8080 / test, hoge fuga was displayed.

Priority was given to setting the project root

Verification 3 Prepare application.properties (yml) for both, but delete one copy on the project root side

In the project root


hoge: hoge

In the hello module


hoge: hogehoge
fuga: fugafuga

If you try to run the application in this state, it will crash and an execution error will occur.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'controller': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'fuga' in value "${fuga}"
...
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'fuga' in value "${fuga}"
...

It seems unlikely that you will get the missing items from application.properties (yml) in another module.

Summary

Even if you create application.properties (yml) for each module and prepare your own setting values, only one application.properties (yml) is prioritized. It seems unlikely that you will get the settings of other modules. If so, it seems better to manage it in the project root or in the main module.

Sample code

https://github.com/eno314/SpringModuleSample

Recommended Posts

Add module with Spring Boot
Download with Spring Boot
Configure Spring Boot application with maven multi module
[Java] Article to add validation with Spring Boot 2.3.1.
Generate barcode with Spring Boot
Hello World with Spring Boot
Implement GraphQL with Spring Boot
Get started with Spring boot
Run LIFF with Spring Boot
SNS login with Spring Boot
File upload with Spring Boot
Spring Boot starting with copy
Hello World with Spring Boot
Getting Started with Spring Boot
Create microservices with Spring Boot
Send email with spring boot
Create an app with Spring Boot 2
Database linkage with doma2 (Spring boot)
Spring Boot programming with VS Code
Until "Hello World" with Spring Boot
Get validation results with Spring Boot
(Intellij) Hello World with Spring Boot
Create an app with Spring Boot
Google Cloud Platform with Spring Boot 2.0.0
Check date correlation with Spring Boot
I tried GraphQL with Spring Boot
[Java] LINE integration with Spring Boot
Beginning with Spring Boot 0. Use Spring CLI
I tried Flyway with Spring Boot
Message cooperation started with Spring Boot
Spring Boot gradle build with Docker
Processing at application startup with Spring Boot
Hello World with Eclipse + Spring Boot + Maven
Send regular notifications with LineNotify + Spring Boot
Perform transaction confirmation test with Spring Boot
Try using Spring Boot with VS Code
Start web application development with Spring Boot
Launch Nginx + Spring Boot application with docker-compose
Implement CRUD with Spring Boot + Thymeleaf + MySQL
Asynchronous processing with Spring Boot using @Async
Implement paging function with Spring Boot + Thymeleaf
Spring Boot Memorandum
gae + spring boot
(IntelliJ + gradle) Hello World with Spring Boot
Use cache with EhCashe 2.x with Spring Boot
Form class validation test with Spring Boot
Add spring boot and gradle to eclipse
Run WEB application with Spring Boot + Thymeleaf
Achieve BASIC authentication with Spring Boot + Spring Security
Spring Boot environment construction with Docker (January 2021 version)
Create a website with Spring Boot + Gradle (jdk1.8.x)
Test controller with Mock MVC in Spring Boot
Asynchronous processing with regular execution in Spring Boot
Until data acquisition with Spring Boot + MyBatis + PostgreSQL
Create a simple search app with Spring Boot
Hash passwords with Spring Boot + Spring Security (with salt, with stretching)
How to use MyBatis2 (iBatis) with Spring Boot 1.4 (Spring 4)
Run Scala applications with Spring Boot through Gradle
How to use built-in h2db with spring boot
Try to implement login function with Spring Boot
How to add a classpath in Spring Boot