springboot_multi_module
springboot_multi_module copied to clipboard
Gradle + Spring Boot + Multi Module
Spring Boot Multi Module using Gradle
Requirements
- Gradle
- IntelliJ
Setup
- IntelliJ --> Create New Project --> Gradle + Java
- GroupId: com; ArtifactId: springboot-multi-module
- Check "use auto-imports"
- Finish
Porject Structure
- Basic project structure,
- If the root has any src/ folder then delete it. No problem.
Create Modules
- We will create two modules:
- common (is a library which can be used by all application modules)
- search (Application module which accepts requests. Search will include common module.)
Module Creation
- Right click on root project --> New --> Module
- Select Gradle + Java
- Give ArtifactId as "common".
- Do next ... Finish
- Now you can see in
root/settings.gradle
we have include 'common'. - Similarly we will create search module.
- Final root/settings.gradle will be as follows,
rootProject.name = 'springboot-multi-module'
include 'common'
include 'search'
Setup common module
- Our common module is just a library. This module will be shared among all the modules. We don't include any web related dependencies here. We just need to say that this is a spring boot application.
-
common/build.gradle
buildscript {
repositories { mavenCentral() }
}
plugins { id "io.spring.dependency-management" version "1.0.4.RELEASE" }
ext { springBootVersion = '2.0.0.RELEASE' }
apply plugin: 'java'
apply plugin: 'idea'
jar {
baseName = 'springboot-multi-module-library'
version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
repositories { mavenCentral() }
dependencies {
compile('org.springframework.boot:spring-boot-starter')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
imports { mavenBom("org.springframework.boot:spring-boot-dependencies:${springBootVersion}") }
}
- Let's create source directory. Right click on common module --> New --> Directory --> src/main/java
- Right click on common/src/main/java --> New --> Package --> com.common
- Create class
Product
(id, name, price) undercom.common
. - That's it. common module is ready to use.
- Do,
./gradlew build
to check the build status.
Setup search application module
- Search module is an application which serves API request and returns response. Hence we need to include web dependency for this module. Web dependency will have tomcat as a transitive dependency. No need to explicitly include tomcat.
- Also search module requires common module. Include it under dependecy as
compile project(':common')
-
search/build.gradle
buildscript {
ext { springBootVersion = '2.0.0.RELEASE' }
repositories { mavenCentral() }
dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") }
}
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
jar {
baseName = 'springboot-multi-module-search'
version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
repositories { mavenCentral() }
dependencies {
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-web')
compile project(':common')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
- Create src/main/java/ directory under search. Create package com.search.
- Create class
SearchApplication
with following code,
package com.search;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.common.Product;
@RestController
@SpringBootApplication(scanBasePackages = "com")
@RequestMapping("/search")
public class SearchApplication {
@RequestMapping("/hello")
@GetMapping
public String hello() {
return "Search: Hello";
}
public static void main(String[] args) {
SpringApplication.run(SearchApplication.class, args);
}
}
NOTE: In the above code main
method is important. This is where Spring Boot will start this module. scanBasePackages
is another important annotation, as it says to scan all the components under the package com
. So ideally all our modules packages are under com
structure. If you have the code in a different package then include it as scanBasePackages = {"com", "another"}
- We will explicitly mention Tomcat server port(as 8100) else it will by default run in
8080
. - Create
resources
directory src/main/ and addapplication.properties
file. Giveserver.port=8100
as property.
Run (let's see whether we are able to access search API or not)
- Under root (springboot-multi-module) --> run,
./gradlew build
to build and then run./gradlew :search:bootRun
to run search application.- First
./gradlew build
will make common library to be compiled and ready to use. - Second,
./gradlew :search:bootRun
will make search application to run on port 8100
- First
- Open Postman/Chrome, http://localhost:8100/search/hello
Create custom class(Product) and use it
- Create another api under search. For now lets call it, "/product"
- Make sure we say this api produces a JSON.
@RequestMapping(value = "/product",
method = RequestMethod.GET,
produces = {"application/json"})
public Product product() {
return new Product(1, "Laptop", 45000d);
}
- Build and Run,
./gradlew build && ./gradlew :search:bootRun
- http://localhost:8100/search/product
{
id: 1,
name: "Laptop",
price: 45000
}
Get particular Product by passing its id using @PathVariable
- NOTE: @PathVariable is to get the value from URL. @RequestBody is used when we pass input as JSON/XML etc. (You will see this usage later)
- Created
com.common.ProductService
for products creation.- To search by id of the product where id is passed as a url param.
- To return a list of products as JSON.
- Add few more apis in search,
@RequestMapping(value = "/product/{id}",
method = RequestMethod.GET,
produces = {"application/json"})
public Product productWith(@PathVariable("id") long id) {
Optional<Product> product = ProductService.getProducts().stream().filter(p -> p.getId() == id).findFirst();
return product.get();
}
@RequestMapping(value = "/products",
method = RequestMethod.GET,
produces = {"application/json"})
public List<Product> products() {
return ProductService.getProducts();
}
Run
- Build & Run in together, ./gradlew build && ./gradlew :search:bootRun
- http://localhost:8100/search/product/1 or http://localhost:8100/search/products
Lets create a POST call to insert a Product
- We can pass a Product as a JSON to api, consume it as JSON and convert it to Product using
@RequestBody
annotation. - In
ProductService
add a method tocreateProduct
and add it to existing products list. - POST method as follows,
@RequestMapping(value = "/product/create",
method = RequestMethod.POST,
consumes = {"application/json"}
)
public String createProduct(@RequestBody Product product) {
if (ProductService.createProduct(product)) {
return "Created Product = " + product.toString();
}
return "Creation failed for Product = " + product.toString();
}
- Open Postman,
- Select POST
- http://localhost:8100/search/product/create
- Body --> raw and select type as JSON.
- Enter the below input in the body placeholder,
{
"name": "Product-10",
"price": 10
}
- Run it and access the above url with JSON as params.
Conclusion
- We have successfully created a Gradle Multi Module Spring Boot application using IntelliJ.