Repository files navigation

SPRING BOOT MULTI MODULE PROJECT

This project is still under development.

This project aims to help the developer to start with spring boot multi-module project quickly. Logging, Exception handling, security are enabled by default. As of now logging and security module are strictly tied to Microsoft azure. All logs and exceptions are continuously tracked in Microsoft Application Insight.

Anyone can take this skeleton, and can start developing Microservice with Spring Boot in no time, since they majorly need to focus on business logic. This project handles major cross-cutting concerns, and these are available under lib folder.

Add your Microservice under application folder. I have added one sample-service under application folder, that can used as a reference.

LIBRARIES

How to bootstrap new Microservice

For Complete implementation, please check sample-service.

  • Step 1:Clone this repository

  • Step 2:Load Parent pon.xml

load_parent_pom

  • Step 3:Create Maven Module

create_maven_module

  • Step 4:Replace pom.xml content
<?xml version="1.0" encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>backend-parent</artifactId>
<groupId>com.app</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sample-service</artifactId> <!--Change the artificat name, if you want -->
<dependencies>
<!-- Enables basic Swagger UI, by adding @EnableDocs annotation on Main Class. For Advance configuration, check README file -->
<dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>
<!-- It contains security, logging and exception dependencies.-->
<dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Check README file for details of this module. -->
<dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Uncomment this section, if you want support for azure blob storage. Check README file for detail usage. --><!-- <dependency> <groupId>com.app</groupId> <artifactId>file-handler</artifactId> <version>${project.version}</version> </dependency>-->
</dependencies>
<build>
<finalName>sample-service</finalName> <!--Change the name of the jar generated by build, if you want -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enable>true</enable>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>
  • Step 5:Add application.yaml file under resource folder
spring:
application:
name: sample-servicedatasource:
url: jdbc:h2:mem:testdbdriver-class-name: org.h2.Driverusername: testpassword: testjpa:
database-platform: org.hibernate.dialect.H2Dialecth2:
console:
enabled: trueautoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfigurationserver:
port: 8080servlet:
session:
cookie:
http-only: truesecure: trueapp:
version: 1.0.0security:
enabled: trueswagger:
enable-auth: falsetitle: Sample Servicedesc: Helps to interact with Backendversion: v1path-mapping: /contact:
name: Backend Teamemail: test@test.comurl: ""license: nulllicense-uri: null
  • Step 6:Create Application.java class under root package
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecurity// UnComment this, if you want to use Security Module. Please refer README for detailed instructionpublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

Library Documentation

This section explains the usage of different modules.

api-docs

Add below dependency to pom.xml

 <dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>

Add below content to application.yml file, to modify the default value swagger variables

app:
swagger:
enable-auth: truetitle: Sample Service APIdesc: Helps to interact with Backendversion: v1path-mapping: /oauth:
client-id: '${backend-client-id}'client-key: '${backend-client}'resource: '${backend-resource}'login-endpoint: '${auth-url}'contact:
name: Backend Teamemail: test@test.comurl: ''license: nulllicense-uri: null

Enable swagger by only adding @EnableDocs annotation on Main Class.

packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication@EnableDocspublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

swagger ui

URL: http://localhost:8080/swagger-ui/index.html

file-handler

Exceptions will be automatically handled by Exception Module

Add below dependency to pom.xml

<dependency>
<groupId>com.app</groupId>
<artifactId>file-handler</artifactId>
<version>${project.version}</version>
</dependency>

Add below content in application.yml file

azure:
storage:
account-name: ${blob-name} account-key: ${blob-key}container-name: ${container-name}

Import FileUtil from file_handler.util

It has 3 functionality:

  • Upload Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicURIuploadBlob(MultipartFilefile, StringblobName) {
returnfileUtil.uploadFile(file, blobName);
}
}
  • Delete Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicvoiddelete(Stringurl, StringblobName) {
fileUtil.deleteBlob(url, blobName);
}
}
  • Download Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicResponseEntity<Resource> download(Stringurl, StringblobName) {
returnfileUtil.downloadBlob(url, blobName);
}
}

exception

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>exception</artifactId>
<version>${project.version}</version>
</dependency>

Below are the exception that are handled by this module:

System Exception

  • ArrayIndexOutOfBoundsException
  • IndexOutOfBoundsException
  • NumberFormatException
  • IllegalArgumentException
  • AccessDeniedException
  • NullPointerException
  • MethodArgumentTypeMismatchException
  • DataAccessException
  • SQLServerException
  • ConstraintViolationException
  • HttpRequestMethodNotSupportedException
  • HttpMediaTypeNotSupportedException
  • MissingPathVariableException
  • HttpMessageNotReadableException
  • HttpMessageNotWritableException
  • MissingServletRequestParameterException
  • ConversionNotSupportedException
  • TypeMismatchException
  • MethodArgumentNotValidException
  • MissingServletRequestPartException
  • NoHandlerFoundException

Custom Exception

  • InvalidStateTransitionException
  • DuplicateRecordException
  • EntityNotFoundException
  • MultipleActionFailedException
  • OperationNotAllowedException
  • OperationFailedException
  • FileHandlingException

logging

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>logging</artifactId>
<version>${project.version}</version>
</dependency>

Out of the box logging for Repository, Service, Controller and Components, once below dependency added to pom.xml, and for all other functions of classes use @Loggable annotation.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@LoggablepublicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

@Loggable has 4 optional parameters, that can set, if want to log some different messages.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@Loggable(valueAfter = "Value After", valueAfterReturning = "Value After Returning", valueAround = "Value Around", valueBefore = "Value Before")
publicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

It will be capturing following properties:

  • class_name: Name of the class to which functions belong.
  • method_name: Name of the method which is getting executed.
  • parameters: Parameters of function.
  • execution_time_in_ms: Time take by a function.
  • microservice: Name of the microservice.
  • request_id: Unique Id with every request, that will also help to trace logs in Application Insight, if used.
  • version: Microservice version.
  • message:
    • When function is starting: FUNCTIONNAME function started..
    • When function complete: FUNCTIONNAME function completed..
    • In case of error it will contain error message.
    • When Controller starts: FUNCTIONNAME event started..
    • When Controller completes: FUNCTIONNAME event completed..

In order to send logs to Application Insight, add below content to application.yml

azure:
application-insights:
instrumentation-key: ${appinsight-instrumentation-key}enabled: true

swagger ui

security

As of now it only supports v1 token.

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>security</artifactId>
<version>${project.version}</version>
</dependency>

Enable security by only adding @EnableSecurity annotation on Main Class.

Add below content to application.yaml, if you are enabling security module

spring:
security.oauth2.client.registration.azure:
client-id: '${client-id-dev}'client-secret: '${client-secret-dev}'client-name: Azureazure:
activedirectory:
client-id: '${client-id-dev}'allow-telemetry: trueclient-secret: '${client-secret-dev}'user-group.allowed-groups: TEST_AZURE_AD_GROUPtenant-id: '${tenant-id-dev}'

If you want to disable out of box spring security, then add below content in application.yaml

spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecuritypublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

utility

Add below dependency to pom.xml, in order to add utility module

 <dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>

It has few important component:

  • ValidList: Use this when you are adding any validators to an element of List.
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}
  • ResponseDTO: Use this DTO, for returning response to Users, for POST, PUT, PATCH, DELETE actions. It has a static method setResponseDTO that can be used, to set the message in response, other fields will be set by default.
    • status: HttpStatus (This will be set to CREATED by default)
    • message: String ( Use setResponseDTO method to set this value, this a static method. ResponseDTO.setResponseDTO( Messages.setMessage(EntityType.USER, ActionType.CREATED, ""))).
    • timestamp: Date (This will set to current timestamp by default. It uses "dd-MM-yyyy hh:mm:ss Z" format).
    • requestId: String ( This will be set by default to unique value for every request. e.g. 123e4567-e89b-12d3-a456-556642440000 )
    • detailMessage: List
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}

About

This project aims to help the developer to quickly bootstrap multi-module project.

Topics

Resources

Stars

16 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

SPRING BOOT MULTI MODULE PROJECT

This project is still under development.

This project aims to help the developer to start with spring boot multi-module project quickly. Logging, Exception handling, security are enabled by default. As of now logging and security module are strictly tied to Microsoft azure. All logs and exceptions are continuously tracked in Microsoft Application Insight.

Anyone can take this skeleton, and can start developing Microservice with Spring Boot in no time, since they majorly need to focus on business logic. This project handles major cross-cutting concerns, and these are available under lib folder.

Add your Microservice under application folder. I have added one sample-service under application folder, that can used as a reference.

LIBRARIES

How to bootstrap new Microservice

For Complete implementation, please check sample-service.

  • Step 1:Clone this repository

  • Step 2:Load Parent pon.xml

load_parent_pom

  • Step 3:Create Maven Module

create_maven_module

  • Step 4:Replace pom.xml content
<?xml version="1.0" encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>backend-parent</artifactId>
<groupId>com.app</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sample-service</artifactId> <!--Change the artificat name, if you want -->
<dependencies>
<!-- Enables basic Swagger UI, by adding @EnableDocs annotation on Main Class. For Advance configuration, check README file -->
<dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>
<!-- It contains security, logging and exception dependencies.-->
<dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Check README file for details of this module. -->
<dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Uncomment this section, if you want support for azure blob storage. Check README file for detail usage. --><!-- <dependency> <groupId>com.app</groupId> <artifactId>file-handler</artifactId> <version>${project.version}</version> </dependency>-->
</dependencies>
<build>
<finalName>sample-service</finalName> <!--Change the name of the jar generated by build, if you want -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enable>true</enable>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>
  • Step 5:Add application.yaml file under resource folder
spring:
application:
name: sample-servicedatasource:
url: jdbc:h2:mem:testdbdriver-class-name: org.h2.Driverusername: testpassword: testjpa:
database-platform: org.hibernate.dialect.H2Dialecth2:
console:
enabled: trueautoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfigurationserver:
port: 8080servlet:
session:
cookie:
http-only: truesecure: trueapp:
version: 1.0.0security:
enabled: trueswagger:
enable-auth: falsetitle: Sample Servicedesc: Helps to interact with Backendversion: v1path-mapping: /contact:
name: Backend Teamemail: test@test.comurl: ""license: nulllicense-uri: null
  • Step 6:Create Application.java class under root package
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecurity// UnComment this, if you want to use Security Module. Please refer README for detailed instructionpublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

Library Documentation

This section explains the usage of different modules.

api-docs

Add below dependency to pom.xml

 <dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>

Add below content to application.yml file, to modify the default value swagger variables

app:
swagger:
enable-auth: truetitle: Sample Service APIdesc: Helps to interact with Backendversion: v1path-mapping: /oauth:
client-id: '${backend-client-id}'client-key: '${backend-client}'resource: '${backend-resource}'login-endpoint: '${auth-url}'contact:
name: Backend Teamemail: test@test.comurl: ''license: nulllicense-uri: null

Enable swagger by only adding @EnableDocs annotation on Main Class.

packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication@EnableDocspublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

swagger ui

URL: http://localhost:8080/swagger-ui/index.html

file-handler

Exceptions will be automatically handled by Exception Module

Add below dependency to pom.xml

<dependency>
<groupId>com.app</groupId>
<artifactId>file-handler</artifactId>
<version>${project.version}</version>
</dependency>

Add below content in application.yml file

azure:
storage:
account-name: ${blob-name} account-key: ${blob-key}container-name: ${container-name}

Import FileUtil from file_handler.util

It has 3 functionality:

  • Upload Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicURIuploadBlob(MultipartFilefile, StringblobName) {
returnfileUtil.uploadFile(file, blobName);
}
}
  • Delete Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicvoiddelete(Stringurl, StringblobName) {
fileUtil.deleteBlob(url, blobName);
}
}
  • Download Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicResponseEntity<Resource> download(Stringurl, StringblobName) {
returnfileUtil.downloadBlob(url, blobName);
}
}

exception

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>exception</artifactId>
<version>${project.version}</version>
</dependency>

Below are the exception that are handled by this module:

System Exception

  • ArrayIndexOutOfBoundsException
  • IndexOutOfBoundsException
  • NumberFormatException
  • IllegalArgumentException
  • AccessDeniedException
  • NullPointerException
  • MethodArgumentTypeMismatchException
  • DataAccessException
  • SQLServerException
  • ConstraintViolationException
  • HttpRequestMethodNotSupportedException
  • HttpMediaTypeNotSupportedException
  • MissingPathVariableException
  • HttpMessageNotReadableException
  • HttpMessageNotWritableException
  • MissingServletRequestParameterException
  • ConversionNotSupportedException
  • TypeMismatchException
  • MethodArgumentNotValidException
  • MissingServletRequestPartException
  • NoHandlerFoundException

Custom Exception

  • InvalidStateTransitionException
  • DuplicateRecordException
  • EntityNotFoundException
  • MultipleActionFailedException
  • OperationNotAllowedException
  • OperationFailedException
  • FileHandlingException

logging

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>logging</artifactId>
<version>${project.version}</version>
</dependency>

Out of the box logging for Repository, Service, Controller and Components, once below dependency added to pom.xml, and for all other functions of classes use @Loggable annotation.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@LoggablepublicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

@Loggable has 4 optional parameters, that can set, if want to log some different messages.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@Loggable(valueAfter = "Value After", valueAfterReturning = "Value After Returning", valueAround = "Value Around", valueBefore = "Value Before")
publicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

It will be capturing following properties:

  • class_name: Name of the class to which functions belong.
  • method_name: Name of the method which is getting executed.
  • parameters: Parameters of function.
  • execution_time_in_ms: Time take by a function.
  • microservice: Name of the microservice.
  • request_id: Unique Id with every request, that will also help to trace logs in Application Insight, if used.
  • version: Microservice version.
  • message:
    • When function is starting: FUNCTIONNAME function started..
    • When function complete: FUNCTIONNAME function completed..
    • In case of error it will contain error message.
    • When Controller starts: FUNCTIONNAME event started..
    • When Controller completes: FUNCTIONNAME event completed..

In order to send logs to Application Insight, add below content to application.yml

azure:
application-insights:
instrumentation-key: ${appinsight-instrumentation-key}enabled: true

swagger ui

security

As of now it only supports v1 token.

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>security</artifactId>
<version>${project.version}</version>
</dependency>

Enable security by only adding @EnableSecurity annotation on Main Class.

Add below content to application.yaml, if you are enabling security module

spring:
security.oauth2.client.registration.azure:
client-id: '${client-id-dev}'client-secret: '${client-secret-dev}'client-name: Azureazure:
activedirectory:
client-id: '${client-id-dev}'allow-telemetry: trueclient-secret: '${client-secret-dev}'user-group.allowed-groups: TEST_AZURE_AD_GROUPtenant-id: '${tenant-id-dev}'

If you want to disable out of box spring security, then add below content in application.yaml

spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecuritypublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

utility

Add below dependency to pom.xml, in order to add utility module

 <dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>

It has few important component:

  • ValidList: Use this when you are adding any validators to an element of List.
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}
  • ResponseDTO: Use this DTO, for returning response to Users, for POST, PUT, PATCH, DELETE actions. It has a static method setResponseDTO that can be used, to set the message in response, other fields will be set by default.
    • status: HttpStatus (This will be set to CREATED by default)
    • message: String ( Use setResponseDTO method to set this value, this a static method. ResponseDTO.setResponseDTO( Messages.setMessage(EntityType.USER, ActionType.CREATED, ""))).
    • timestamp: Date (This will set to current timestamp by default. It uses "dd-MM-yyyy hh:mm:ss Z" format).
    • requestId: String ( This will be set by default to unique value for every request. e.g. 123e4567-e89b-12d3-a456-556642440000 )
    • detailMessage: List
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}

About

This project aims to help the developer to quickly bootstrap multi-module project.

Topics

Resources

Stars

16 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SPRING BOOT MULTI MODULE PROJECT

This project is still under development.

This project aims to help the developer to start with spring boot multi-module project quickly. Logging, Exception handling, security are enabled by default. As of now logging and security module are strictly tied to Microsoft azure. All logs and exceptions are continuously tracked in Microsoft Application Insight.

Anyone can take this skeleton, and can start developing Microservice with Spring Boot in no time, since they majorly need to focus on business logic. This project handles major cross-cutting concerns, and these are available under lib folder.

Add your Microservice under application folder. I have added one sample-service under application folder, that can used as a reference.

LIBRARIES

How to bootstrap new Microservice

For Complete implementation, please check sample-service.

  • Step 1:Clone this repository

  • Step 2:Load Parent pon.xml

load_parent_pom

  • Step 3:Create Maven Module

create_maven_module

  • Step 4:Replace pom.xml content
<?xml version="1.0" encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>backend-parent</artifactId>
<groupId>com.app</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sample-service</artifactId> <!--Change the artificat name, if you want -->
<dependencies>
<!-- Enables basic Swagger UI, by adding @EnableDocs annotation on Main Class. For Advance configuration, check README file -->
<dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>
<!-- It contains security, logging and exception dependencies.-->
<dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Check README file for details of this module. -->
<dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Uncomment this section, if you want support for azure blob storage. Check README file for detail usage. --><!-- <dependency> <groupId>com.app</groupId> <artifactId>file-handler</artifactId> <version>${project.version}</version> </dependency>-->
</dependencies>
<build>
<finalName>sample-service</finalName> <!--Change the name of the jar generated by build, if you want -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enable>true</enable>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>
  • Step 5:Add application.yaml file under resource folder
spring:
application:
name: sample-servicedatasource:
url: jdbc:h2:mem:testdbdriver-class-name: org.h2.Driverusername: testpassword: testjpa:
database-platform: org.hibernate.dialect.H2Dialecth2:
console:
enabled: trueautoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfigurationserver:
port: 8080servlet:
session:
cookie:
http-only: truesecure: trueapp:
version: 1.0.0security:
enabled: trueswagger:
enable-auth: falsetitle: Sample Servicedesc: Helps to interact with Backendversion: v1path-mapping: /contact:
name: Backend Teamemail: test@test.comurl: ""license: nulllicense-uri: null
  • Step 6:Create Application.java class under root package
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecurity// UnComment this, if you want to use Security Module. Please refer README for detailed instructionpublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

Library Documentation

This section explains the usage of different modules.

api-docs

Add below dependency to pom.xml

 <dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>

Add below content to application.yml file, to modify the default value swagger variables

app:
swagger:
enable-auth: truetitle: Sample Service APIdesc: Helps to interact with Backendversion: v1path-mapping: /oauth:
client-id: '${backend-client-id}'client-key: '${backend-client}'resource: '${backend-resource}'login-endpoint: '${auth-url}'contact:
name: Backend Teamemail: test@test.comurl: ''license: nulllicense-uri: null

Enable swagger by only adding @EnableDocs annotation on Main Class.

packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication@EnableDocspublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

swagger ui

URL: http://localhost:8080/swagger-ui/index.html

file-handler

Exceptions will be automatically handled by Exception Module

Add below dependency to pom.xml

<dependency>
<groupId>com.app</groupId>
<artifactId>file-handler</artifactId>
<version>${project.version}</version>
</dependency>

Add below content in application.yml file

azure:
storage:
account-name: ${blob-name} account-key: ${blob-key}container-name: ${container-name}

Import FileUtil from file_handler.util

It has 3 functionality:

  • Upload Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicURIuploadBlob(MultipartFilefile, StringblobName) {
returnfileUtil.uploadFile(file, blobName);
}
}
  • Delete Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicvoiddelete(Stringurl, StringblobName) {
fileUtil.deleteBlob(url, blobName);
}
}
  • Download Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicResponseEntity<Resource> download(Stringurl, StringblobName) {
returnfileUtil.downloadBlob(url, blobName);
}
}

exception

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>exception</artifactId>
<version>${project.version}</version>
</dependency>

Below are the exception that are handled by this module:

System Exception

  • ArrayIndexOutOfBoundsException
  • IndexOutOfBoundsException
  • NumberFormatException
  • IllegalArgumentException
  • AccessDeniedException
  • NullPointerException
  • MethodArgumentTypeMismatchException
  • DataAccessException
  • SQLServerException
  • ConstraintViolationException
  • HttpRequestMethodNotSupportedException
  • HttpMediaTypeNotSupportedException
  • MissingPathVariableException
  • HttpMessageNotReadableException
  • HttpMessageNotWritableException
  • MissingServletRequestParameterException
  • ConversionNotSupportedException
  • TypeMismatchException
  • MethodArgumentNotValidException
  • MissingServletRequestPartException
  • NoHandlerFoundException

Custom Exception

  • InvalidStateTransitionException
  • DuplicateRecordException
  • EntityNotFoundException
  • MultipleActionFailedException
  • OperationNotAllowedException
  • OperationFailedException
  • FileHandlingException

logging

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>logging</artifactId>
<version>${project.version}</version>
</dependency>

Out of the box logging for Repository, Service, Controller and Components, once below dependency added to pom.xml, and for all other functions of classes use @Loggable annotation.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@LoggablepublicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

@Loggable has 4 optional parameters, that can set, if want to log some different messages.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@Loggable(valueAfter = "Value After", valueAfterReturning = "Value After Returning", valueAround = "Value Around", valueBefore = "Value Before")
publicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

It will be capturing following properties:

  • class_name: Name of the class to which functions belong.
  • method_name: Name of the method which is getting executed.
  • parameters: Parameters of function.
  • execution_time_in_ms: Time take by a function.
  • microservice: Name of the microservice.
  • request_id: Unique Id with every request, that will also help to trace logs in Application Insight, if used.
  • version: Microservice version.
  • message:
    • When function is starting: FUNCTIONNAME function started..
    • When function complete: FUNCTIONNAME function completed..
    • In case of error it will contain error message.
    • When Controller starts: FUNCTIONNAME event started..
    • When Controller completes: FUNCTIONNAME event completed..

In order to send logs to Application Insight, add below content to application.yml

azure:
application-insights:
instrumentation-key: ${appinsight-instrumentation-key}enabled: true

swagger ui

security

As of now it only supports v1 token.

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>security</artifactId>
<version>${project.version}</version>
</dependency>

Enable security by only adding @EnableSecurity annotation on Main Class.

Add below content to application.yaml, if you are enabling security module

spring:
security.oauth2.client.registration.azure:
client-id: '${client-id-dev}'client-secret: '${client-secret-dev}'client-name: Azureazure:
activedirectory:
client-id: '${client-id-dev}'allow-telemetry: trueclient-secret: '${client-secret-dev}'user-group.allowed-groups: TEST_AZURE_AD_GROUPtenant-id: '${tenant-id-dev}'

If you want to disable out of box spring security, then add below content in application.yaml

spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecuritypublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

utility

Add below dependency to pom.xml, in order to add utility module

 <dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>

It has few important component:

  • ValidList: Use this when you are adding any validators to an element of List.
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}
  • ResponseDTO: Use this DTO, for returning response to Users, for POST, PUT, PATCH, DELETE actions. It has a static method setResponseDTO that can be used, to set the message in response, other fields will be set by default.
    • status: HttpStatus (This will be set to CREATED by default)
    • message: String ( Use setResponseDTO method to set this value, this a static method. ResponseDTO.setResponseDTO( Messages.setMessage(EntityType.USER, ActionType.CREATED, ""))).
    • timestamp: Date (This will set to current timestamp by default. It uses "dd-MM-yyyy hh:mm:ss Z" format).
    • requestId: String ( This will be set by default to unique value for every request. e.g. 123e4567-e89b-12d3-a456-556642440000 )
    • detailMessage: List
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}

About

This project aims to help the developer to quickly bootstrap multi-module project.

Topics

Resources

Stars

16 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SPRING BOOT MULTI MODULE PROJECT

This project is still under development.

This project aims to help the developer to start with spring boot multi-module project quickly. Logging, Exception handling, security are enabled by default. As of now logging and security module are strictly tied to Microsoft azure. All logs and exceptions are continuously tracked in Microsoft Application Insight.

Anyone can take this skeleton, and can start developing Microservice with Spring Boot in no time, since they majorly need to focus on business logic. This project handles major cross-cutting concerns, and these are available under lib folder.

Add your Microservice under application folder. I have added one sample-service under application folder, that can used as a reference.

LIBRARIES

How to bootstrap new Microservice

For Complete implementation, please check sample-service.

  • Step 1:Clone this repository

  • Step 2:Load Parent pon.xml

load_parent_pom

  • Step 3:Create Maven Module

create_maven_module

  • Step 4:Replace pom.xml content
<?xml version="1.0" encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>backend-parent</artifactId>
<groupId>com.app</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sample-service</artifactId> <!--Change the artificat name, if you want -->
<dependencies>
<!-- Enables basic Swagger UI, by adding @EnableDocs annotation on Main Class. For Advance configuration, check README file -->
<dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>
<!-- It contains security, logging and exception dependencies.-->
<dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Check README file for details of this module. -->
<dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Uncomment this section, if you want support for azure blob storage. Check README file for detail usage. --><!-- <dependency> <groupId>com.app</groupId> <artifactId>file-handler</artifactId> <version>${project.version}</version> </dependency>-->
</dependencies>
<build>
<finalName>sample-service</finalName> <!--Change the name of the jar generated by build, if you want -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enable>true</enable>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>
  • Step 5:Add application.yaml file under resource folder
spring:
application:
name: sample-servicedatasource:
url: jdbc:h2:mem:testdbdriver-class-name: org.h2.Driverusername: testpassword: testjpa:
database-platform: org.hibernate.dialect.H2Dialecth2:
console:
enabled: trueautoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfigurationserver:
port: 8080servlet:
session:
cookie:
http-only: truesecure: trueapp:
version: 1.0.0security:
enabled: trueswagger:
enable-auth: falsetitle: Sample Servicedesc: Helps to interact with Backendversion: v1path-mapping: /contact:
name: Backend Teamemail: test@test.comurl: ""license: nulllicense-uri: null
  • Step 6:Create Application.java class under root package
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecurity// UnComment this, if you want to use Security Module. Please refer README for detailed instructionpublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

Library Documentation

This section explains the usage of different modules.

api-docs

Add below dependency to pom.xml

 <dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>

Add below content to application.yml file, to modify the default value swagger variables

app:
swagger:
enable-auth: truetitle: Sample Service APIdesc: Helps to interact with Backendversion: v1path-mapping: /oauth:
client-id: '${backend-client-id}'client-key: '${backend-client}'resource: '${backend-resource}'login-endpoint: '${auth-url}'contact:
name: Backend Teamemail: test@test.comurl: ''license: nulllicense-uri: null

Enable swagger by only adding @EnableDocs annotation on Main Class.

packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication@EnableDocspublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

swagger ui

URL: http://localhost:8080/swagger-ui/index.html

file-handler

Exceptions will be automatically handled by Exception Module

Add below dependency to pom.xml

<dependency>
<groupId>com.app</groupId>
<artifactId>file-handler</artifactId>
<version>${project.version}</version>
</dependency>

Add below content in application.yml file

azure:
storage:
account-name: ${blob-name} account-key: ${blob-key}container-name: ${container-name}

Import FileUtil from file_handler.util

It has 3 functionality:

  • Upload Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicURIuploadBlob(MultipartFilefile, StringblobName) {
returnfileUtil.uploadFile(file, blobName);
}
}
  • Delete Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicvoiddelete(Stringurl, StringblobName) {
fileUtil.deleteBlob(url, blobName);
}
}
  • Download Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicResponseEntity<Resource> download(Stringurl, StringblobName) {
returnfileUtil.downloadBlob(url, blobName);
}
}

exception

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>exception</artifactId>
<version>${project.version}</version>
</dependency>

Below are the exception that are handled by this module:

System Exception

  • ArrayIndexOutOfBoundsException
  • IndexOutOfBoundsException
  • NumberFormatException
  • IllegalArgumentException
  • AccessDeniedException
  • NullPointerException
  • MethodArgumentTypeMismatchException
  • DataAccessException
  • SQLServerException
  • ConstraintViolationException
  • HttpRequestMethodNotSupportedException
  • HttpMediaTypeNotSupportedException
  • MissingPathVariableException
  • HttpMessageNotReadableException
  • HttpMessageNotWritableException
  • MissingServletRequestParameterException
  • ConversionNotSupportedException
  • TypeMismatchException
  • MethodArgumentNotValidException
  • MissingServletRequestPartException
  • NoHandlerFoundException

Custom Exception

  • InvalidStateTransitionException
  • DuplicateRecordException
  • EntityNotFoundException
  • MultipleActionFailedException
  • OperationNotAllowedException
  • OperationFailedException
  • FileHandlingException

logging

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>logging</artifactId>
<version>${project.version}</version>
</dependency>

Out of the box logging for Repository, Service, Controller and Components, once below dependency added to pom.xml, and for all other functions of classes use @Loggable annotation.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@LoggablepublicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

@Loggable has 4 optional parameters, that can set, if want to log some different messages.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@Loggable(valueAfter = "Value After", valueAfterReturning = "Value After Returning", valueAround = "Value Around", valueBefore = "Value Before")
publicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

It will be capturing following properties:

  • class_name: Name of the class to which functions belong.
  • method_name: Name of the method which is getting executed.
  • parameters: Parameters of function.
  • execution_time_in_ms: Time take by a function.
  • microservice: Name of the microservice.
  • request_id: Unique Id with every request, that will also help to trace logs in Application Insight, if used.
  • version: Microservice version.
  • message:
    • When function is starting: FUNCTIONNAME function started..
    • When function complete: FUNCTIONNAME function completed..
    • In case of error it will contain error message.
    • When Controller starts: FUNCTIONNAME event started..
    • When Controller completes: FUNCTIONNAME event completed..

In order to send logs to Application Insight, add below content to application.yml

azure:
application-insights:
instrumentation-key: ${appinsight-instrumentation-key}enabled: true

swagger ui

security

As of now it only supports v1 token.

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>security</artifactId>
<version>${project.version}</version>
</dependency>

Enable security by only adding @EnableSecurity annotation on Main Class.

Add below content to application.yaml, if you are enabling security module

spring:
security.oauth2.client.registration.azure:
client-id: '${client-id-dev}'client-secret: '${client-secret-dev}'client-name: Azureazure:
activedirectory:
client-id: '${client-id-dev}'allow-telemetry: trueclient-secret: '${client-secret-dev}'user-group.allowed-groups: TEST_AZURE_AD_GROUPtenant-id: '${tenant-id-dev}'

If you want to disable out of box spring security, then add below content in application.yaml

spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecuritypublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

utility

Add below dependency to pom.xml, in order to add utility module

 <dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>

It has few important component:

  • ValidList: Use this when you are adding any validators to an element of List.
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}
  • ResponseDTO: Use this DTO, for returning response to Users, for POST, PUT, PATCH, DELETE actions. It has a static method setResponseDTO that can be used, to set the message in response, other fields will be set by default.
    • status: HttpStatus (This will be set to CREATED by default)
    • message: String ( Use setResponseDTO method to set this value, this a static method. ResponseDTO.setResponseDTO( Messages.setMessage(EntityType.USER, ActionType.CREATED, ""))).
    • timestamp: Date (This will set to current timestamp by default. It uses "dd-MM-yyyy hh:mm:ss Z" format).
    • requestId: String ( This will be set by default to unique value for every request. e.g. 123e4567-e89b-12d3-a456-556642440000 )
    • detailMessage: List
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}

About

This project aims to help the developer to quickly bootstrap multi-module project.

Topics

Resources

Stars

16 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

SPRING BOOT MULTI MODULE PROJECT

This project is still under development.

This project aims to help the developer to start with spring boot multi-module project quickly. Logging, Exception handling, security are enabled by default. As of now logging and security module are strictly tied to Microsoft azure. All logs and exceptions are continuously tracked in Microsoft Application Insight.

Anyone can take this skeleton, and can start developing Microservice with Spring Boot in no time, since they majorly need to focus on business logic. This project handles major cross-cutting concerns, and these are available under lib folder.

Add your Microservice under application folder. I have added one sample-service under application folder, that can used as a reference.

LIBRARIES

How to bootstrap new Microservice

For Complete implementation, please check sample-service.

  • Step 1:Clone this repository

  • Step 2:Load Parent pon.xml

load_parent_pom

  • Step 3:Create Maven Module

create_maven_module

  • Step 4:Replace pom.xml content
<?xml version="1.0" encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>backend-parent</artifactId>
<groupId>com.app</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sample-service</artifactId> <!--Change the artificat name, if you want -->
<dependencies>
<!-- Enables basic Swagger UI, by adding @EnableDocs annotation on Main Class. For Advance configuration, check README file -->
<dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>
<!-- It contains security, logging and exception dependencies.-->
<dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Check README file for details of this module. -->
<dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Uncomment this section, if you want support for azure blob storage. Check README file for detail usage. --><!-- <dependency> <groupId>com.app</groupId> <artifactId>file-handler</artifactId> <version>${project.version}</version> </dependency>-->
</dependencies>
<build>
<finalName>sample-service</finalName> <!--Change the name of the jar generated by build, if you want -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enable>true</enable>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>
  • Step 5:Add application.yaml file under resource folder
spring:
application:
name: sample-servicedatasource:
url: jdbc:h2:mem:testdbdriver-class-name: org.h2.Driverusername: testpassword: testjpa:
database-platform: org.hibernate.dialect.H2Dialecth2:
console:
enabled: trueautoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfigurationserver:
port: 8080servlet:
session:
cookie:
http-only: truesecure: trueapp:
version: 1.0.0security:
enabled: trueswagger:
enable-auth: falsetitle: Sample Servicedesc: Helps to interact with Backendversion: v1path-mapping: /contact:
name: Backend Teamemail: test@test.comurl: ""license: nulllicense-uri: null
  • Step 6:Create Application.java class under root package
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecurity// UnComment this, if you want to use Security Module. Please refer README for detailed instructionpublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

Library Documentation

This section explains the usage of different modules.

api-docs

Add below dependency to pom.xml

 <dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>

Add below content to application.yml file, to modify the default value swagger variables

app:
swagger:
enable-auth: truetitle: Sample Service APIdesc: Helps to interact with Backendversion: v1path-mapping: /oauth:
client-id: '${backend-client-id}'client-key: '${backend-client}'resource: '${backend-resource}'login-endpoint: '${auth-url}'contact:
name: Backend Teamemail: test@test.comurl: ''license: nulllicense-uri: null

Enable swagger by only adding @EnableDocs annotation on Main Class.

packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication@EnableDocspublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

swagger ui

URL: http://localhost:8080/swagger-ui/index.html

file-handler

Exceptions will be automatically handled by Exception Module

Add below dependency to pom.xml

<dependency>
<groupId>com.app</groupId>
<artifactId>file-handler</artifactId>
<version>${project.version}</version>
</dependency>

Add below content in application.yml file

azure:
storage:
account-name: ${blob-name} account-key: ${blob-key}container-name: ${container-name}

Import FileUtil from file_handler.util

It has 3 functionality:

  • Upload Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicURIuploadBlob(MultipartFilefile, StringblobName) {
returnfileUtil.uploadFile(file, blobName);
}
}
  • Delete Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicvoiddelete(Stringurl, StringblobName) {
fileUtil.deleteBlob(url, blobName);
}
}
  • Download Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicResponseEntity<Resource> download(Stringurl, StringblobName) {
returnfileUtil.downloadBlob(url, blobName);
}
}

exception

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>exception</artifactId>
<version>${project.version}</version>
</dependency>

Below are the exception that are handled by this module:

System Exception

  • ArrayIndexOutOfBoundsException
  • IndexOutOfBoundsException
  • NumberFormatException
  • IllegalArgumentException
  • AccessDeniedException
  • NullPointerException
  • MethodArgumentTypeMismatchException
  • DataAccessException
  • SQLServerException
  • ConstraintViolationException
  • HttpRequestMethodNotSupportedException
  • HttpMediaTypeNotSupportedException
  • MissingPathVariableException
  • HttpMessageNotReadableException
  • HttpMessageNotWritableException
  • MissingServletRequestParameterException
  • ConversionNotSupportedException
  • TypeMismatchException
  • MethodArgumentNotValidException
  • MissingServletRequestPartException
  • NoHandlerFoundException

Custom Exception

  • InvalidStateTransitionException
  • DuplicateRecordException
  • EntityNotFoundException
  • MultipleActionFailedException
  • OperationNotAllowedException
  • OperationFailedException
  • FileHandlingException

logging

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>logging</artifactId>
<version>${project.version}</version>
</dependency>

Out of the box logging for Repository, Service, Controller and Components, once below dependency added to pom.xml, and for all other functions of classes use @Loggable annotation.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@LoggablepublicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

@Loggable has 4 optional parameters, that can set, if want to log some different messages.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@Loggable(valueAfter = "Value After", valueAfterReturning = "Value After Returning", valueAround = "Value Around", valueBefore = "Value Before")
publicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

It will be capturing following properties:

  • class_name: Name of the class to which functions belong.
  • method_name: Name of the method which is getting executed.
  • parameters: Parameters of function.
  • execution_time_in_ms: Time take by a function.
  • microservice: Name of the microservice.
  • request_id: Unique Id with every request, that will also help to trace logs in Application Insight, if used.
  • version: Microservice version.
  • message:
    • When function is starting: FUNCTIONNAME function started..
    • When function complete: FUNCTIONNAME function completed..
    • In case of error it will contain error message.
    • When Controller starts: FUNCTIONNAME event started..
    • When Controller completes: FUNCTIONNAME event completed..

In order to send logs to Application Insight, add below content to application.yml

azure:
application-insights:
instrumentation-key: ${appinsight-instrumentation-key}enabled: true

swagger ui

security

As of now it only supports v1 token.

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>security</artifactId>
<version>${project.version}</version>
</dependency>

Enable security by only adding @EnableSecurity annotation on Main Class.

Add below content to application.yaml, if you are enabling security module

spring:
security.oauth2.client.registration.azure:
client-id: '${client-id-dev}'client-secret: '${client-secret-dev}'client-name: Azureazure:
activedirectory:
client-id: '${client-id-dev}'allow-telemetry: trueclient-secret: '${client-secret-dev}'user-group.allowed-groups: TEST_AZURE_AD_GROUPtenant-id: '${tenant-id-dev}'

If you want to disable out of box spring security, then add below content in application.yaml

spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecuritypublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

utility

Add below dependency to pom.xml, in order to add utility module

 <dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>

It has few important component:

  • ValidList: Use this when you are adding any validators to an element of List.
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}
  • ResponseDTO: Use this DTO, for returning response to Users, for POST, PUT, PATCH, DELETE actions. It has a static method setResponseDTO that can be used, to set the message in response, other fields will be set by default.
    • status: HttpStatus (This will be set to CREATED by default)
    • message: String ( Use setResponseDTO method to set this value, this a static method. ResponseDTO.setResponseDTO( Messages.setMessage(EntityType.USER, ActionType.CREATED, ""))).
    • timestamp: Date (This will set to current timestamp by default. It uses "dd-MM-yyyy hh:mm:ss Z" format).
    • requestId: String ( This will be set by default to unique value for every request. e.g. 123e4567-e89b-12d3-a456-556642440000 )
    • detailMessage: List
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}

About

This project aims to help the developer to quickly bootstrap multi-module project.

Topics

Resources

Stars

16 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SPRING BOOT MULTI MODULE PROJECT

This project is still under development.

This project aims to help the developer to start with spring boot multi-module project quickly. Logging, Exception handling, security are enabled by default. As of now logging and security module are strictly tied to Microsoft azure. All logs and exceptions are continuously tracked in Microsoft Application Insight.

Anyone can take this skeleton, and can start developing Microservice with Spring Boot in no time, since they majorly need to focus on business logic. This project handles major cross-cutting concerns, and these are available under lib folder.

Add your Microservice under application folder. I have added one sample-service under application folder, that can used as a reference.

LIBRARIES

How to bootstrap new Microservice

For Complete implementation, please check sample-service.

  • Step 1:Clone this repository

  • Step 2:Load Parent pon.xml

load_parent_pom

  • Step 3:Create Maven Module

create_maven_module

  • Step 4:Replace pom.xml content
<?xml version="1.0" encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>backend-parent</artifactId>
<groupId>com.app</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sample-service</artifactId> <!--Change the artificat name, if you want -->
<dependencies>
<!-- Enables basic Swagger UI, by adding @EnableDocs annotation on Main Class. For Advance configuration, check README file -->
<dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>
<!-- It contains security, logging and exception dependencies.-->
<dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Check README file for details of this module. -->
<dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Uncomment this section, if you want support for azure blob storage. Check README file for detail usage. --><!-- <dependency> <groupId>com.app</groupId> <artifactId>file-handler</artifactId> <version>${project.version}</version> </dependency>-->
</dependencies>
<build>
<finalName>sample-service</finalName> <!--Change the name of the jar generated by build, if you want -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enable>true</enable>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>
  • Step 5:Add application.yaml file under resource folder
spring:
application:
name: sample-servicedatasource:
url: jdbc:h2:mem:testdbdriver-class-name: org.h2.Driverusername: testpassword: testjpa:
database-platform: org.hibernate.dialect.H2Dialecth2:
console:
enabled: trueautoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfigurationserver:
port: 8080servlet:
session:
cookie:
http-only: truesecure: trueapp:
version: 1.0.0security:
enabled: trueswagger:
enable-auth: falsetitle: Sample Servicedesc: Helps to interact with Backendversion: v1path-mapping: /contact:
name: Backend Teamemail: test@test.comurl: ""license: nulllicense-uri: null
  • Step 6:Create Application.java class under root package
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecurity// UnComment this, if you want to use Security Module. Please refer README for detailed instructionpublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

Library Documentation

This section explains the usage of different modules.

api-docs

Add below dependency to pom.xml

 <dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>

Add below content to application.yml file, to modify the default value swagger variables

app:
swagger:
enable-auth: truetitle: Sample Service APIdesc: Helps to interact with Backendversion: v1path-mapping: /oauth:
client-id: '${backend-client-id}'client-key: '${backend-client}'resource: '${backend-resource}'login-endpoint: '${auth-url}'contact:
name: Backend Teamemail: test@test.comurl: ''license: nulllicense-uri: null

Enable swagger by only adding @EnableDocs annotation on Main Class.

packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication@EnableDocspublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

swagger ui

URL: http://localhost:8080/swagger-ui/index.html

file-handler

Exceptions will be automatically handled by Exception Module

Add below dependency to pom.xml

<dependency>
<groupId>com.app</groupId>
<artifactId>file-handler</artifactId>
<version>${project.version}</version>
</dependency>

Add below content in application.yml file

azure:
storage:
account-name: ${blob-name} account-key: ${blob-key}container-name: ${container-name}

Import FileUtil from file_handler.util

It has 3 functionality:

  • Upload Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicURIuploadBlob(MultipartFilefile, StringblobName) {
returnfileUtil.uploadFile(file, blobName);
}
}
  • Delete Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicvoiddelete(Stringurl, StringblobName) {
fileUtil.deleteBlob(url, blobName);
}
}
  • Download Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicResponseEntity<Resource> download(Stringurl, StringblobName) {
returnfileUtil.downloadBlob(url, blobName);
}
}

exception

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>exception</artifactId>
<version>${project.version}</version>
</dependency>

Below are the exception that are handled by this module:

System Exception

  • ArrayIndexOutOfBoundsException
  • IndexOutOfBoundsException
  • NumberFormatException
  • IllegalArgumentException
  • AccessDeniedException
  • NullPointerException
  • MethodArgumentTypeMismatchException
  • DataAccessException
  • SQLServerException
  • ConstraintViolationException
  • HttpRequestMethodNotSupportedException
  • HttpMediaTypeNotSupportedException
  • MissingPathVariableException
  • HttpMessageNotReadableException
  • HttpMessageNotWritableException
  • MissingServletRequestParameterException
  • ConversionNotSupportedException
  • TypeMismatchException
  • MethodArgumentNotValidException
  • MissingServletRequestPartException
  • NoHandlerFoundException

Custom Exception

  • InvalidStateTransitionException
  • DuplicateRecordException
  • EntityNotFoundException
  • MultipleActionFailedException
  • OperationNotAllowedException
  • OperationFailedException
  • FileHandlingException

logging

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>logging</artifactId>
<version>${project.version}</version>
</dependency>

Out of the box logging for Repository, Service, Controller and Components, once below dependency added to pom.xml, and for all other functions of classes use @Loggable annotation.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@LoggablepublicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

@Loggable has 4 optional parameters, that can set, if want to log some different messages.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@Loggable(valueAfter = "Value After", valueAfterReturning = "Value After Returning", valueAround = "Value Around", valueBefore = "Value Before")
publicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

It will be capturing following properties:

  • class_name: Name of the class to which functions belong.
  • method_name: Name of the method which is getting executed.
  • parameters: Parameters of function.
  • execution_time_in_ms: Time take by a function.
  • microservice: Name of the microservice.
  • request_id: Unique Id with every request, that will also help to trace logs in Application Insight, if used.
  • version: Microservice version.
  • message:
    • When function is starting: FUNCTIONNAME function started..
    • When function complete: FUNCTIONNAME function completed..
    • In case of error it will contain error message.
    • When Controller starts: FUNCTIONNAME event started..
    • When Controller completes: FUNCTIONNAME event completed..

In order to send logs to Application Insight, add below content to application.yml

azure:
application-insights:
instrumentation-key: ${appinsight-instrumentation-key}enabled: true

swagger ui

security

As of now it only supports v1 token.

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>security</artifactId>
<version>${project.version}</version>
</dependency>

Enable security by only adding @EnableSecurity annotation on Main Class.

Add below content to application.yaml, if you are enabling security module

spring:
security.oauth2.client.registration.azure:
client-id: '${client-id-dev}'client-secret: '${client-secret-dev}'client-name: Azureazure:
activedirectory:
client-id: '${client-id-dev}'allow-telemetry: trueclient-secret: '${client-secret-dev}'user-group.allowed-groups: TEST_AZURE_AD_GROUPtenant-id: '${tenant-id-dev}'

If you want to disable out of box spring security, then add below content in application.yaml

spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecuritypublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

utility

Add below dependency to pom.xml, in order to add utility module

 <dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>

It has few important component:

  • ValidList: Use this when you are adding any validators to an element of List.
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}
  • ResponseDTO: Use this DTO, for returning response to Users, for POST, PUT, PATCH, DELETE actions. It has a static method setResponseDTO that can be used, to set the message in response, other fields will be set by default.
    • status: HttpStatus (This will be set to CREATED by default)
    • message: String ( Use setResponseDTO method to set this value, this a static method. ResponseDTO.setResponseDTO( Messages.setMessage(EntityType.USER, ActionType.CREATED, ""))).
    • timestamp: Date (This will set to current timestamp by default. It uses "dd-MM-yyyy hh:mm:ss Z" format).
    • requestId: String ( This will be set by default to unique value for every request. e.g. 123e4567-e89b-12d3-a456-556642440000 )
    • detailMessage: List
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}

About

This project aims to help the developer to quickly bootstrap multi-module project.

Topics

Resources

Stars

16 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SPRING BOOT MULTI MODULE PROJECT

This project is still under development.

This project aims to help the developer to start with spring boot multi-module project quickly. Logging, Exception handling, security are enabled by default. As of now logging and security module are strictly tied to Microsoft azure. All logs and exceptions are continuously tracked in Microsoft Application Insight.

Anyone can take this skeleton, and can start developing Microservice with Spring Boot in no time, since they majorly need to focus on business logic. This project handles major cross-cutting concerns, and these are available under lib folder.

Add your Microservice under application folder. I have added one sample-service under application folder, that can used as a reference.

LIBRARIES

How to bootstrap new Microservice

For Complete implementation, please check sample-service.

  • Step 1:Clone this repository

  • Step 2:Load Parent pon.xml

load_parent_pom

  • Step 3:Create Maven Module

create_maven_module

  • Step 4:Replace pom.xml content
<?xml version="1.0" encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>backend-parent</artifactId>
<groupId>com.app</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sample-service</artifactId> <!--Change the artificat name, if you want -->
<dependencies>
<!-- Enables basic Swagger UI, by adding @EnableDocs annotation on Main Class. For Advance configuration, check README file -->
<dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>
<!-- It contains security, logging and exception dependencies.-->
<dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Check README file for details of this module. -->
<dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Uncomment this section, if you want support for azure blob storage. Check README file for detail usage. --><!-- <dependency> <groupId>com.app</groupId> <artifactId>file-handler</artifactId> <version>${project.version}</version> </dependency>-->
</dependencies>
<build>
<finalName>sample-service</finalName> <!--Change the name of the jar generated by build, if you want -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enable>true</enable>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>
  • Step 5:Add application.yaml file under resource folder
spring:
application:
name: sample-servicedatasource:
url: jdbc:h2:mem:testdbdriver-class-name: org.h2.Driverusername: testpassword: testjpa:
database-platform: org.hibernate.dialect.H2Dialecth2:
console:
enabled: trueautoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfigurationserver:
port: 8080servlet:
session:
cookie:
http-only: truesecure: trueapp:
version: 1.0.0security:
enabled: trueswagger:
enable-auth: falsetitle: Sample Servicedesc: Helps to interact with Backendversion: v1path-mapping: /contact:
name: Backend Teamemail: test@test.comurl: ""license: nulllicense-uri: null
  • Step 6:Create Application.java class under root package
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecurity// UnComment this, if you want to use Security Module. Please refer README for detailed instructionpublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

Library Documentation

This section explains the usage of different modules.

api-docs

Add below dependency to pom.xml

 <dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>

Add below content to application.yml file, to modify the default value swagger variables

app:
swagger:
enable-auth: truetitle: Sample Service APIdesc: Helps to interact with Backendversion: v1path-mapping: /oauth:
client-id: '${backend-client-id}'client-key: '${backend-client}'resource: '${backend-resource}'login-endpoint: '${auth-url}'contact:
name: Backend Teamemail: test@test.comurl: ''license: nulllicense-uri: null

Enable swagger by only adding @EnableDocs annotation on Main Class.

packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication@EnableDocspublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

swagger ui

URL: http://localhost:8080/swagger-ui/index.html

file-handler

Exceptions will be automatically handled by Exception Module

Add below dependency to pom.xml

<dependency>
<groupId>com.app</groupId>
<artifactId>file-handler</artifactId>
<version>${project.version}</version>
</dependency>

Add below content in application.yml file

azure:
storage:
account-name: ${blob-name} account-key: ${blob-key}container-name: ${container-name}

Import FileUtil from file_handler.util

It has 3 functionality:

  • Upload Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicURIuploadBlob(MultipartFilefile, StringblobName) {
returnfileUtil.uploadFile(file, blobName);
}
}
  • Delete Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicvoiddelete(Stringurl, StringblobName) {
fileUtil.deleteBlob(url, blobName);
}
}
  • Download Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicResponseEntity<Resource> download(Stringurl, StringblobName) {
returnfileUtil.downloadBlob(url, blobName);
}
}

exception

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>exception</artifactId>
<version>${project.version}</version>
</dependency>

Below are the exception that are handled by this module:

System Exception

  • ArrayIndexOutOfBoundsException
  • IndexOutOfBoundsException
  • NumberFormatException
  • IllegalArgumentException
  • AccessDeniedException
  • NullPointerException
  • MethodArgumentTypeMismatchException
  • DataAccessException
  • SQLServerException
  • ConstraintViolationException
  • HttpRequestMethodNotSupportedException
  • HttpMediaTypeNotSupportedException
  • MissingPathVariableException
  • HttpMessageNotReadableException
  • HttpMessageNotWritableException
  • MissingServletRequestParameterException
  • ConversionNotSupportedException
  • TypeMismatchException
  • MethodArgumentNotValidException
  • MissingServletRequestPartException
  • NoHandlerFoundException

Custom Exception

  • InvalidStateTransitionException
  • DuplicateRecordException
  • EntityNotFoundException
  • MultipleActionFailedException
  • OperationNotAllowedException
  • OperationFailedException
  • FileHandlingException

logging

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>logging</artifactId>
<version>${project.version}</version>
</dependency>

Out of the box logging for Repository, Service, Controller and Components, once below dependency added to pom.xml, and for all other functions of classes use @Loggable annotation.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@LoggablepublicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

@Loggable has 4 optional parameters, that can set, if want to log some different messages.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@Loggable(valueAfter = "Value After", valueAfterReturning = "Value After Returning", valueAround = "Value Around", valueBefore = "Value Before")
publicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

It will be capturing following properties:

  • class_name: Name of the class to which functions belong.
  • method_name: Name of the method which is getting executed.
  • parameters: Parameters of function.
  • execution_time_in_ms: Time take by a function.
  • microservice: Name of the microservice.
  • request_id: Unique Id with every request, that will also help to trace logs in Application Insight, if used.
  • version: Microservice version.
  • message:
    • When function is starting: FUNCTIONNAME function started..
    • When function complete: FUNCTIONNAME function completed..
    • In case of error it will contain error message.
    • When Controller starts: FUNCTIONNAME event started..
    • When Controller completes: FUNCTIONNAME event completed..

In order to send logs to Application Insight, add below content to application.yml

azure:
application-insights:
instrumentation-key: ${appinsight-instrumentation-key}enabled: true

swagger ui

security

As of now it only supports v1 token.

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>security</artifactId>
<version>${project.version}</version>
</dependency>

Enable security by only adding @EnableSecurity annotation on Main Class.

Add below content to application.yaml, if you are enabling security module

spring:
security.oauth2.client.registration.azure:
client-id: '${client-id-dev}'client-secret: '${client-secret-dev}'client-name: Azureazure:
activedirectory:
client-id: '${client-id-dev}'allow-telemetry: trueclient-secret: '${client-secret-dev}'user-group.allowed-groups: TEST_AZURE_AD_GROUPtenant-id: '${tenant-id-dev}'

If you want to disable out of box spring security, then add below content in application.yaml

spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecuritypublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

utility

Add below dependency to pom.xml, in order to add utility module

 <dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>

It has few important component:

  • ValidList: Use this when you are adding any validators to an element of List.
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}
  • ResponseDTO: Use this DTO, for returning response to Users, for POST, PUT, PATCH, DELETE actions. It has a static method setResponseDTO that can be used, to set the message in response, other fields will be set by default.
    • status: HttpStatus (This will be set to CREATED by default)
    • message: String ( Use setResponseDTO method to set this value, this a static method. ResponseDTO.setResponseDTO( Messages.setMessage(EntityType.USER, ActionType.CREATED, ""))).
    • timestamp: Date (This will set to current timestamp by default. It uses "dd-MM-yyyy hh:mm:ss Z" format).
    • requestId: String ( This will be set by default to unique value for every request. e.g. 123e4567-e89b-12d3-a456-556642440000 )
    • detailMessage: List
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}

About

This project aims to help the developer to quickly bootstrap multi-module project.

Topics

Resources

Stars

16 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

SPRING BOOT MULTI MODULE PROJECT

This project is still under development.

This project aims to help the developer to start with spring boot multi-module project quickly. Logging, Exception handling, security are enabled by default. As of now logging and security module are strictly tied to Microsoft azure. All logs and exceptions are continuously tracked in Microsoft Application Insight.

Anyone can take this skeleton, and can start developing Microservice with Spring Boot in no time, since they majorly need to focus on business logic. This project handles major cross-cutting concerns, and these are available under lib folder.

Add your Microservice under application folder. I have added one sample-service under application folder, that can used as a reference.

LIBRARIES

How to bootstrap new Microservice

For Complete implementation, please check sample-service.

  • Step 1:Clone this repository

  • Step 2:Load Parent pon.xml

load_parent_pom

  • Step 3:Create Maven Module

create_maven_module

  • Step 4:Replace pom.xml content
<?xml version="1.0" encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>backend-parent</artifactId>
<groupId>com.app</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sample-service</artifactId> <!--Change the artificat name, if you want -->
<dependencies>
<!-- Enables basic Swagger UI, by adding @EnableDocs annotation on Main Class. For Advance configuration, check README file -->
<dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>
<!-- It contains security, logging and exception dependencies.-->
<dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Check README file for details of this module. -->
<dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Uncomment this section, if you want support for azure blob storage. Check README file for detail usage. --><!-- <dependency> <groupId>com.app</groupId> <artifactId>file-handler</artifactId> <version>${project.version}</version> </dependency>-->
</dependencies>
<build>
<finalName>sample-service</finalName> <!--Change the name of the jar generated by build, if you want -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enable>true</enable>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>
  • Step 5:Add application.yaml file under resource folder
spring:
application:
name: sample-servicedatasource:
url: jdbc:h2:mem:testdbdriver-class-name: org.h2.Driverusername: testpassword: testjpa:
database-platform: org.hibernate.dialect.H2Dialecth2:
console:
enabled: trueautoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfigurationserver:
port: 8080servlet:
session:
cookie:
http-only: truesecure: trueapp:
version: 1.0.0security:
enabled: trueswagger:
enable-auth: falsetitle: Sample Servicedesc: Helps to interact with Backendversion: v1path-mapping: /contact:
name: Backend Teamemail: test@test.comurl: ""license: nulllicense-uri: null
  • Step 6:Create Application.java class under root package
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecurity// UnComment this, if you want to use Security Module. Please refer README for detailed instructionpublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

Library Documentation

This section explains the usage of different modules.

api-docs

Add below dependency to pom.xml

 <dependency>
<groupId>com.app</groupId>
<artifactId>api-docs</artifactId>
<version>${project.version}</version>
</dependency>

Add below content to application.yml file, to modify the default value swagger variables

app:
swagger:
enable-auth: truetitle: Sample Service APIdesc: Helps to interact with Backendversion: v1path-mapping: /oauth:
client-id: '${backend-client-id}'client-key: '${backend-client}'resource: '${backend-resource}'login-endpoint: '${auth-url}'contact:
name: Backend Teamemail: test@test.comurl: ''license: nulllicense-uri: null

Enable swagger by only adding @EnableDocs annotation on Main Class.

packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication@EnableDocspublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

swagger ui

URL: http://localhost:8080/swagger-ui/index.html

file-handler

Exceptions will be automatically handled by Exception Module

Add below dependency to pom.xml

<dependency>
<groupId>com.app</groupId>
<artifactId>file-handler</artifactId>
<version>${project.version}</version>
</dependency>

Add below content in application.yml file

azure:
storage:
account-name: ${blob-name} account-key: ${blob-key}container-name: ${container-name}

Import FileUtil from file_handler.util

It has 3 functionality:

  • Upload Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicURIuploadBlob(MultipartFilefile, StringblobName) {
returnfileUtil.uploadFile(file, blobName);
}
}
  • Delete Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicvoiddelete(Stringurl, StringblobName) {
fileUtil.deleteBlob(url, blobName);
}
}
  • Download Blob
packagefile_handler;
importfile_handler.util.FileUtil;
publicclassFileHandler {
@AutowiredprivateFileUtilfileUtil;
publicResponseEntity<Resource> download(Stringurl, StringblobName) {
returnfileUtil.downloadBlob(url, blobName);
}
}

exception

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>exception</artifactId>
<version>${project.version}</version>
</dependency>

Below are the exception that are handled by this module:

System Exception

  • ArrayIndexOutOfBoundsException
  • IndexOutOfBoundsException
  • NumberFormatException
  • IllegalArgumentException
  • AccessDeniedException
  • NullPointerException
  • MethodArgumentTypeMismatchException
  • DataAccessException
  • SQLServerException
  • ConstraintViolationException
  • HttpRequestMethodNotSupportedException
  • HttpMediaTypeNotSupportedException
  • MissingPathVariableException
  • HttpMessageNotReadableException
  • HttpMessageNotWritableException
  • MissingServletRequestParameterException
  • ConversionNotSupportedException
  • TypeMismatchException
  • MethodArgumentNotValidException
  • MissingServletRequestPartException
  • NoHandlerFoundException

Custom Exception

  • InvalidStateTransitionException
  • DuplicateRecordException
  • EntityNotFoundException
  • MultipleActionFailedException
  • OperationNotAllowedException
  • OperationFailedException
  • FileHandlingException

logging

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>logging</artifactId>
<version>${project.version}</version>
</dependency>

Out of the box logging for Repository, Service, Controller and Components, once below dependency added to pom.xml, and for all other functions of classes use @Loggable annotation.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@LoggablepublicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

@Loggable has 4 optional parameters, that can set, if want to log some different messages.

packagesample_service.dto.mapper;
importlogging.annotations.Loggable;
importsample_service.dto.model.AppModelDTO;
importsample_service.model.AppModel;
publicclassAppModelMapper {
@Loggable(valueAfter = "Value After", valueAfterReturning = "Value After Returning", valueAround = "Value Around", valueBefore = "Value Before")
publicAppModelconvertToModel(AppModelDTOmodelDTO) {
AppModelmodel = newAppModel();
model.setId(modelDTO.getId());
model.setName(modelDTO.getName());
returnmodel;
}
}

It will be capturing following properties:

  • class_name: Name of the class to which functions belong.
  • method_name: Name of the method which is getting executed.
  • parameters: Parameters of function.
  • execution_time_in_ms: Time take by a function.
  • microservice: Name of the microservice.
  • request_id: Unique Id with every request, that will also help to trace logs in Application Insight, if used.
  • version: Microservice version.
  • message:
    • When function is starting: FUNCTIONNAME function started..
    • When function complete: FUNCTIONNAME function completed..
    • In case of error it will contain error message.
    • When Controller starts: FUNCTIONNAME event started..
    • When Controller completes: FUNCTIONNAME event completed..

In order to send logs to Application Insight, add below content to application.yml

azure:
application-insights:
instrumentation-key: ${appinsight-instrumentation-key}enabled: true

swagger ui

security

As of now it only supports v1 token.

It is already a part of backend starter

 <dependency>
<groupId>com.app</groupId>
<artifactId>backend-starter</artifactId>
<version>${project.version}</version>
</dependency>

If you are not adding backend starter, then it can be added individually as well

 <dependency>
<groupId>com.app</groupId>
<artifactId>security</artifactId>
<version>${project.version}</version>
</dependency>

Enable security by only adding @EnableSecurity annotation on Main Class.

Add below content to application.yaml, if you are enabling security module

spring:
security.oauth2.client.registration.azure:
client-id: '${client-id-dev}'client-secret: '${client-secret-dev}'client-name: Azureazure:
activedirectory:
client-id: '${client-id-dev}'allow-telemetry: trueclient-secret: '${client-secret-dev}'user-group.allowed-groups: TEST_AZURE_AD_GROUPtenant-id: '${tenant-id-dev}'

If you want to disable out of box spring security, then add below content in application.yaml

spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
packagesample_service;
importapidocs.annotations.EnableDocs;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importsecurity.annotations.EnableSecurity;
@SpringBootApplication@EnableDocs@EnableSecuritypublicclassApplication {
publicstaticvoidmain( String[] args ) { SpringApplication.run(Application.class, args);}
}

utility

Add below dependency to pom.xml, in order to add utility module

 <dependency>
<groupId>com.app</groupId>
<artifactId>utility</artifactId>
<version>${project.version}</version>
</dependency>

It has few important component:

  • ValidList: Use this when you are adding any validators to an element of List.
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}
  • ResponseDTO: Use this DTO, for returning response to Users, for POST, PUT, PATCH, DELETE actions. It has a static method setResponseDTO that can be used, to set the message in response, other fields will be set by default.
    • status: HttpStatus (This will be set to CREATED by default)
    • message: String ( Use setResponseDTO method to set this value, this a static method. ResponseDTO.setResponseDTO( Messages.setMessage(EntityType.USER, ActionType.CREATED, ""))).
    • timestamp: Date (This will set to current timestamp by default. It uses "dd-MM-yyyy hh:mm:ss Z" format).
    • requestId: String ( This will be set by default to unique value for every request. e.g. 123e4567-e89b-12d3-a456-556642440000 )
    • detailMessage: List
packagesample_service.controller.v1.api;
importutility.annotations.ControllerV1;
@ControllerV1publicclassAppController {
@PostMapping(path = "/user")
publicResponseEntity<ResponseDTO> setUsersDetail(@Valid@RequestBodyValidList<AppRequest> request) {
returnnewResponseEntity( ResponseDTO.setResponseDTO(
Messages.setMessage(EntityType.USER, ActionType.CREATED, "")),
HttpStatus.CREATED
);
}}

About

This project aims to help the developer to quickly bootstrap multi-module project.

Topics

Resources

Stars

16 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages