-
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.external-config
-
@Value
-
@ConfigurationProperties(prefix = "app")
-
we can create internal static class in main class of property configuration and we can access
- Property coniguration should be read only meaning no one can update those properties values later , for that we have to make that prperty class as Immutable
- Remove all setters , fields shoud be final and create constructor
- @ConstructorBinding use this annotation for configuration using constructor
- https://www.youtube.com/watch?v=2dPon1G5S-M&list=PLuNxlOYbv61jFFX2ARQKnBgkMF6DvEEic&index=1&ab_channel=SivaLabs
- https://github.com/sivaprasadreddy/sivalabs-youtube-code-samples
- Dependecymanagment tag : we can exclude any transative dependency and we can define in parent project as POM
- Default Values ex. applicartion.properties
- Profile specific overrides ex. application-{profie}.properties
- environment variables ex. SERVER_PORT=9090
- we can validate property file fields using @Validate
- We can bind propertiy files with Record from jdk16+
- By using the MDC, you can enrich log statements with contextual information such as user identifiers, request IDs, session IDs, transaction IDs, or any other relevant data that can help in understanding the log events in the context of the application's execution flow.
- https://howtodoinjava.com/logback/logging-with-mapped-diagnostic-context
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<layout>
<Pattern>%d{DATE} %p %X{sessionId} %X{userId} %c - %m%n</Pattern>
</layout>
</appender>
#logging.level.root=INFO
#logging.level.com.sivalabs=TRACE
#logging.pattern.console=%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID:- }){magenta} %clr(UserId:%X{UserId:-Guest}){magenta} %clr(Context:%X){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n
#logging.file.name=myapp.log
<configuration>
<springProperty scope="context" name="region" source="app.region" defaultValue="us-east-1"/>
<property name="LOG_FILE" value="${region}-myapp.log"/>
<property name="CONSOLE_LOG_PATTERN" value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID:- }){magenta} %clr(UserId:%X{UserId:-Guest}){magenta} %clr(Context:%X){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n ${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } [UserId:%X{UserId:-Guest}] [Context:%X] --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
<springProfile name="local">
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
</springProfile>
<springProfile name="!local">
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</springProfile>
<logger name="com.sivalabs" level="DEBUG"/>
<logger name="org.springframework" level="INFO"/>
</configuration>
- @WebMvcTest
@WebMvcTest(controllers = ProductController.class)
class ProductControllerTest {
@MockBean
private ProductService productService;
@Autowired
private MockMvc mockMvc;
@Test
void shouldReturnActiveProducts() throws Exception {
BDDMockito.given(productService.getAllProducts()).willReturn(List.of());
mockMvc.perform(get("/api/products"))
.andExpect(status().isOk());
}
}
- https://github.com/sivaprasadreddy/sivalabs-youtube-code-samples/tree/main/spring-boot-exception-handling
- Web project exception handling
- Customize white error page using template
- Rest exception handling
- Customize error response payload using @ExceptionHandler
- @ControllerAdvice or @RestControllerAdvice
- https://github.com/zalando/problem-spring-web
- When add this starter dependecy in project will get exception handling by default with proper http status code and message
- Internally usinbg ProblemAutoconfiguration
@RestControllerAdvice
class ExceptionHandling implements ProblemHandling {
@ExceptionHandler
public ResponseEntity<Problem> handle(CustomerNotFoundException e, NativeWebRequest request) {
ThrowableProblem problem = Problem.builder().withStatus(Status.NOT_FOUND)
.withTitle("Customer Not Found")
.withDetail(e.getMessage())
.build();
return create(problem, request);
}
}
spring.boot.admin.client.url=http://localhost:9090
management.endpoints.web.exposure.include=*
management.endpoint.health.show-components=always
management.endpoint.health.show-details=always
management.info.env.enabled=true
management.info.java.enabled=true
management.info.os.enabled=true
info.myapp.name=ActuatorDemo
info.myapp.version=1.0.1
info.myapp.author=SivaLabs
info.myapp.website=https://sivalabs.in
[email protected]@
[email protected]@
[email protected]@
- https://github.com/sivaprasadreddy/sivalabs-youtube-code-samples/tree/main/spring-boot-admin-server
- https://github.com/codecentric/spring-boot-admin
- Add Spring Boot Admin Server starter to your dependencies:
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
@SpringBootApplication
@EnableAdminServer
public class SpringBootAdminServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAdminServerApplication.class, args);
}
}
- Add spring-boot-admin-starter-client to your dependencies:
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
spring.boot.admin.client.url=http://localhost:8080 (1)
management.endpoints.web.exposure.include=* (2)
management.info.env.enabled=true (3)
- https://github.com/sivaprasadreddy/sivalabs-youtube-code-samples/tree/main/spring-boot-openapi-swagger
- swagger docs can be generate by two libs sprningFox and OpenApi
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.9</version>
</dependency>
- For secutiry authorization at global
@Configuration
@OpenAPIDefinition(info = @Info(title = "SpringBoot Tips API", version = "v1"))
@SecurityScheme(
name = "jwtBearerAuth",
type = SecuritySchemeType.HTTP,
bearerFormat = "JWT",
scheme = "bearer"
)
public class SwaggerConfig {
}
@RestController
@RequestMapping("/api/bookmarks")
@RequiredArgsConstructor
@SecurityRequirement(name = "jwtBearerAuth")
@Tag(name = "Bookmarks")
public class BookmarkController {
private final BookmarkService bookmarkService;
@GetMapping
public List<Bookmark> getAllBookmarks() {
return bookmarkService.getAllBookmarks();
}
@GetMapping("/{id}")
public ResponseEntity<Bookmark> getBookmarkById(@PathVariable Long id) {
Bookmark bookmark = bookmarkService.getBookmarkById(id);
return ResponseEntity.ok(bookmark);
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
@PreAuthorize("hasRole('ROLE_ADMIN')")
//@Operation(description = "Create a new bookmark", security = @SecurityRequirement(name = "jwtBearerAuth"))
@ApiResponses(
value = {
@ApiResponse(description = "Successfully created new bookmark", responseCode = "201"),
@ApiResponse(description = "Forbidden", responseCode = "403"),
}
)
public Bookmark createBookmark(@RequestBody @Valid Bookmark bookmark) {
return bookmarkService.createBookmark(bookmark);
}
}