Merge remote-tracking branch 'upstream/master' into feature/BAEL-6695-BooleanValidation

This commit is contained in:
Niket Agrawal
2023-10-14 21:24:01 +05:30
198 changed files with 3200 additions and 640 deletions
@@ -25,6 +25,8 @@ import com.baeldung.testcontainers.support.MiddleEarthCharactersRepository;
@Testcontainers
@SpringBootTest(webEnvironment = DEFINED_PORT)
@DirtiesContext(classMode = AFTER_CLASS)
// Testcontainers require a valid docker installation.
// When running the tests, ensure you have a valid Docker environment
class DynamicPropertiesLiveTest {
@Container
static MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"));
@@ -8,6 +8,9 @@ import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.utility.DockerImageName;
// Testcontainers require a valid docker installation.
// When running the app locally, ensure you have a valid Docker environment
class LocalDevApplication {
public static void main(String[] args) {
@@ -24,6 +24,8 @@ import com.baeldung.testcontainers.support.MiddleEarthCharactersRepository;
@Testcontainers
@SpringBootTest(webEnvironment = DEFINED_PORT)
@DirtiesContext(classMode = AFTER_CLASS)
// Testcontainers require a valid docker installation.
// When running the tests, ensure you have a valid Docker environment
class ServiceConnectionLiveTest {
@Container
+6 -2
View File
@@ -60,7 +60,11 @@
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-commons</artifactId>
<version>1.10.0</version>
</dependency>
<dependency>
<groupId>org.mock-server</groupId>
@@ -204,7 +208,7 @@
<properties>
<java.version>19</java.version>
<mapstruct.version>1.5.2.Final</mapstruct.version>
<springdoc.version>2.0.0</springdoc.version>
<springdoc.version>2.2.0</springdoc.version>
<maven-surefire-plugin.version>3.0.0-M7</maven-surefire-plugin.version>
<start-class>com.baeldung.sample.TodoApplication</start-class>
<mockserver.version>5.14.0</mockserver.version>
@@ -6,6 +6,8 @@ public class Article {
Integer id;
String title;
public Article() {}
public Article(Integer id, String title) {
this.id = id;
this.title = title;
@@ -19,6 +21,14 @@ public class Article {
return title;
}
public void setId(Integer id) {
this.id = id;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -1,5 +1,6 @@
package com.baeldung.restclient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
@@ -13,13 +14,21 @@ public class ArticleController {
Map<Integer, Article> database = new HashMap<>();
@GetMapping
public Collection<Article> getArticles() {
return database.values();
public ResponseEntity<Collection<Article>> getArticles() {
Collection<Article> values = database.values();
if (values.isEmpty()) {
return ResponseEntity.noContent().build();
}
return ResponseEntity.ok(values);
}
@GetMapping("/{id}")
public Article getArticle(@PathVariable Integer id) {
return database.get(id);
public ResponseEntity<Article> getArticle(@PathVariable("id") Integer id) {
Article article = database.get(id);
if (article == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(article);
}
@PostMapping
@@ -28,7 +37,7 @@ public class ArticleController {
}
@PutMapping("/{id}")
public void updateArticle(@PathVariable Integer id, @RequestBody Article article) {
public void updateArticle(@PathVariable("id") Integer id, @RequestBody Article article) {
assert Objects.equals(id, article.getId());
database.remove(id);
database.put(id, article);
@@ -0,0 +1,6 @@
package com.baeldung.restclient;
public class ArticleNotFoundException extends RuntimeException {
public ArticleNotFoundException() {
}
}
@@ -0,0 +1,6 @@
package com.baeldung.restclient;
public class InvalidArticleResponseException extends RuntimeException {
public InvalidArticleResponseException() {
}
}
@@ -1,17 +1,23 @@
package com.baeldung.restclient;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestClient;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@@ -22,7 +28,10 @@ public class RestClientIntegrationTest {
private String uriBase;
RestClient restClient = RestClient.create();
@BeforeAll
@Autowired
ObjectMapper objectMapper;
@BeforeEach
public void setup() {
uriBase = "http://localhost:" + port;
}
@@ -42,7 +51,7 @@ public class RestClientIntegrationTest {
.retrieve()
.body(String.class);
assertThat(articlesAsString).isEqualTo("[]");
assertThat(articlesAsString).isEqualTo("");
}
@Test
@@ -63,6 +72,48 @@ public class RestClientIntegrationTest {
assertThat(articles).isEqualTo(List.of(article));
}
@Test
void shouldPostAndGetArticlesWithExchange() {
assertThatThrownBy(this::getArticlesWithExchange).isInstanceOf(ArticleNotFoundException.class);
Article article = new Article(1, "How to use RestClient");
restClient.post()
.uri(uriBase + "/articles")
.contentType(MediaType.APPLICATION_JSON)
.body(article)
.retrieve()
.toBodilessEntity();
List<Article> articles = getArticlesWithExchange();
assertThat(articles).isEqualTo(List.of(article));
}
private List<Article> getArticlesWithExchange() {
return restClient.get()
.uri(uriBase + "/articles")
.exchange((request, response) -> {
if (response.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(204))) {
throw new ArticleNotFoundException();
} else if (response.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(200))) {
return objectMapper.readValue(response.getBody(), new TypeReference<>() {});
} else {
throw new InvalidArticleResponseException();
}
});
}
@Test
void shouldPostAndGetArticlesWithErrorHandling() {
assertThatThrownBy(() -> {
restClient.get()
.uri(uriBase + "/articles/1234")
.retrieve()
.onStatus(status -> status.value() == 404, (request, response) -> { throw new ArticleNotFoundException(); })
.body(new ParameterizedTypeReference<>() {});
}).isInstanceOf(ArticleNotFoundException.class);
}
@Test
void shouldPostAndPutAndGetArticles() {
Article article = new Article(1, "How to use RestClient");
@@ -79,7 +130,7 @@ public class RestClientIntegrationTest {
.contentType(MediaType.APPLICATION_JSON)
.body(articleChanged)
.retrieve()
.toBodilessEntity();
.toBodilessEntity();
List<Article> articles = restClient.get()
.uri(uriBase + "/articles")
@@ -104,11 +155,12 @@ public class RestClientIntegrationTest {
.retrieve()
.toBodilessEntity();
List<Article> articles = restClient.get()
ResponseEntity<Void> entity = restClient.get()
.uri(uriBase + "/articles")
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.body(new ParameterizedTypeReference<>() {});
.toBodilessEntity();
assertThat(articles).isEqualTo(List.of());
assertThat(entity.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(204));
}
}
@@ -9,9 +9,10 @@
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>spring-boot-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-3</relativePath>
</parent>
<dependencies>
@@ -47,13 +48,12 @@
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>${rest-assured.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cloud-connectors</artifactId>
<version>${spring-boot-cloud-connectors.version}</version>
</dependency>
</dependencies>
@@ -332,6 +332,7 @@
<servlet.version>4.0.0</servlet.version>
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
<spring-cloud-gcp.version>1.0.0.RELEASE</spring-cloud-gcp.version>
<spring-boot-cloud-connectors.version>2.2.13.RELEASE</spring-boot-cloud-connectors.version>
</properties>
</project>
@@ -4,6 +4,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@@ -12,12 +13,11 @@ public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.permitAll()
.and()
.csrf()
.disable();
http.authorizeHttpRequests(expressionInterceptUrlRegistry ->
expressionInterceptUrlRegistry
.anyRequest()
.permitAll())
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
}
@@ -1,10 +1,10 @@
package com.baeldung.persistence.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Book {
@@ -102,7 +102,7 @@
</build>
<properties>
<start-class>com.baeldung.keycloak.SpringBoot</start-class>
<start-class>com.baeldung.keycloak.SpringBootKeycloakApp</start-class>
<jaxb-runtime.version>4.0.0</jaxb-runtime.version>
<wsdl4j.version>1.6.3</wsdl4j.version>
<jaxb2-maven-plugin.version>2.5.0</jaxb2-maven-plugin.version>
@@ -6,11 +6,10 @@ import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class SpringBoot {
public class SpringBootKeycloakApp {
public static void main(String[] args) {
SpringApplication.run(SpringBoot.class, args);
SpringApplication.run(SpringBootKeycloakApp.class, args);
}
@Bean
@@ -4,10 +4,9 @@ import org.junit.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.baeldung.keycloak.SpringBoot;
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = { SpringBoot.class })
@SpringBootTest(classes = { SpringBootKeycloakApp.class })
public class KeycloakContextIntegrationTest {
@Test
@@ -0,0 +1,2 @@
## Relevant Articles
- [Difference Between permitAll() and anonymous() in Spring Security](https://www.baeldung.com/spring-security-permitall-vs-anonymous)
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-security-2</artifactId>
<name>spring-boot-security-1</name>
<packaging>jar</packaging>
<description>Spring Boot Security Auto-Configuration</description>
<parent>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>spring-boot-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -13,7 +13,7 @@ public class EcommerceController {
return "Show Cart";
}
//can we accessed by both anonymous and authenticated users
//can be accessed by both anonymous and authenticated users
@GetMapping("/public/showProducts")
public @ResponseBody String listProducts() {
return "List Products";
@@ -11,7 +11,6 @@ This module contains articles about Spring Boot Security
- [Disable Security for a Profile in Spring Boot](https://www.baeldung.com/spring-security-disable-profile)
- [Spring @EnableWebSecurity vs. @EnableGlobalMethodSecurity](https://www.baeldung.com/spring-enablewebsecurity-vs-enableglobalmethodsecurity)
- [Spring Security Configuring Different URLs](https://www.baeldung.com/spring-security-configuring-urls)
- [Difference Between permitAll() and anonymous() in Spring Security](https://www.baeldung.com/spring-security-permitall-vs-anonymous)
### Spring Boot Security Auto-Configuration
@@ -3,10 +3,11 @@ package com.baeldung.swaggerkeycloak;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
@@ -24,16 +25,19 @@ public class GlobalSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.requestMatchers(HttpMethod.OPTIONS)
http.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests((requests) -> requests.requestMatchers(HttpMethod.OPTIONS)
.permitAll()
.requestMatchers("/api/**")
.authenticated()
.anyRequest()
.permitAll();
http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
.permitAll());
http.oauth2ResourceServer((oauth2) -> oauth2
.jwt(Customizer.withDefaults())
);
return http.build();
}
@@ -13,4 +13,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Spring Web Service Integration Tests with @WebServiceServerTest](https://www.baeldung.com/spring-webserviceservertest)
- [Spring Boot Testing Redis With Testcontainers](https://www.baeldung.com/spring-boot-redis-testcontainers)
- [Spring Boot Keycloak Integration Testing with Testcontainers](https://www.baeldung.com/spring-boot-keycloak-integration-testing)
- [Difference Between @Spy and @SpyBean](https://www.baeldung.com/spring-spy-vs-spybean)
- More articles: [[<-- prev]](../spring-boot-testing)