Merge branch 'eugenp:master' into PR-6910
This commit is contained in:
@@ -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>
|
||||
@@ -273,7 +277,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;
|
||||
|
||||
+14
-5
@@ -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);
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package com.baeldung.restclient;
|
||||
|
||||
public class ArticleNotFoundException extends RuntimeException {
|
||||
public ArticleNotFoundException() {
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package com.baeldung.restclient;
|
||||
|
||||
public class InvalidArticleResponseException extends RuntimeException {
|
||||
public InvalidArticleResponseException() {
|
||||
}
|
||||
}
|
||||
+59
-7
@@ -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>This is simple boot application for Spring boot actuator test</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>
|
||||
@@ -39,16 +40,6 @@
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
||||
+43
-23
@@ -1,36 +1,56 @@
|
||||
package com.baeldung.endpoints.enabling;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.Customizer;
|
||||
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.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
@Configuration
|
||||
public class SecurityConfiguration {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
auth.inMemoryAuthentication()
|
||||
.withUser("user")
|
||||
.password(encoder.encode("password"))
|
||||
.roles("USER")
|
||||
.and()
|
||||
.withUser("admin")
|
||||
.password(encoder.encode("admin"))
|
||||
.roles("USER", "ADMIN");
|
||||
@Bean
|
||||
MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
|
||||
return new MvcRequestMatcher.Builder(introspector);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint())
|
||||
.authorizeRequests((requests) -> requests.anyRequest()
|
||||
.hasRole("ADMIN"));
|
||||
http.httpBasic();
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception {
|
||||
http.httpBasic(Customizer.withDefaults());
|
||||
http.securityMatcher(EndpointRequest.toAnyEndpoint());
|
||||
http.authorizeHttpRequests(authz -> {
|
||||
authz.requestMatchers(mvc.pattern("/actuator/**"))
|
||||
.hasRole("ADMIN")
|
||||
.anyRequest()
|
||||
.authenticated();
|
||||
});
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Bean
|
||||
public InMemoryUserDetailsManager userDetailsService() {
|
||||
UserDetails user = User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build();
|
||||
UserDetails admin = User.withDefaultPasswordEncoder()
|
||||
.username("admin")
|
||||
.password("password")
|
||||
.roles("USER", "ADMIN")
|
||||
.build();
|
||||
return new InMemoryUserDetailsManager(user, admin);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
package com.baeldung.endpoints.info;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.web.context.request.RequestContextListener;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import jakarta.servlet.ServletContext;
|
||||
|
||||
@EnableScheduling
|
||||
@ComponentScan("com.baeldung.metrics")
|
||||
|
||||
+8
-8
@@ -7,14 +7,14 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.FilterConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@Component
|
||||
public class MetricFilter implements Filter {
|
||||
|
||||
+3
-3
@@ -13,20 +13,20 @@ import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
public class EndpointEnablingIntegrationTest {
|
||||
class EndpointEnablingIntegrationTest {
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
@WithMockUser(username = "user", password = "password", roles = "USER")
|
||||
public void givenWrongAuthentication_whenCallingActuator_thenReturns401() throws Exception {
|
||||
void givenWrongAuthentication_whenCallingActuator_thenReturns401() throws Exception {
|
||||
mockMvc.perform(get("/actuator"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
|
||||
public void givenProperAuthentication_whenCallingActuator_thenReturnsExpectedEndpoints() throws Exception {
|
||||
void givenProperAuthentication_whenCallingActuator_thenReturnsExpectedEndpoints() throws Exception {
|
||||
mockMvc.perform(get("/actuator"))
|
||||
.andExpect(jsonPath("$._links").exists())
|
||||
.andExpect(jsonPath("$._links.beans").exists())
|
||||
|
||||
@@ -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>
|
||||
+6
-6
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -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 {
|
||||
|
||||
@@ -93,8 +93,8 @@
|
||||
|
||||
<properties>
|
||||
<swagger-core-jakarta.version>2.2.11</swagger-core-jakarta.version>
|
||||
<springwolf-kafka.version>0.12.1</springwolf-kafka.version>
|
||||
<springwolf-ui.version>0.8.0</springwolf-ui.version>
|
||||
<springwolf-kafka.version>0.14.0</springwolf-kafka.version>
|
||||
<springwolf-ui.version>0.14.0</springwolf-ui.version>
|
||||
<testcontainers-kafka.version>1.18.3</testcontainers-kafka.version>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
"operationId": "incoming-topic_publish",
|
||||
"description": "More details for the incoming topic",
|
||||
"bindings": {
|
||||
"kafka": { }
|
||||
"kafka": {
|
||||
"bindingVersion": "0.4.0"
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0",
|
||||
@@ -32,7 +34,9 @@
|
||||
"$ref": "#/components/schemas/SpringKafkaDefaultHeadersIncomingPayloadDto"
|
||||
},
|
||||
"bindings": {
|
||||
"kafka": { }
|
||||
"kafka": {
|
||||
"bindingVersion": "0.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +46,9 @@
|
||||
"operationId": "outgoing-topic_subscribe",
|
||||
"description": "More details for the outgoing topic",
|
||||
"bindings": {
|
||||
"kafka": { }
|
||||
"kafka": {
|
||||
"bindingVersion": "0.4.0"
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0",
|
||||
@@ -56,7 +62,9 @@
|
||||
"$ref": "#/components/schemas/SpringKafkaDefaultHeadersOutgoingPayloadDto"
|
||||
},
|
||||
"bindings": {
|
||||
"kafka": { }
|
||||
"kafka": {
|
||||
"bindingVersion": "0.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
## Relevant Articles
|
||||
- [Create a GraalVM Docker Image](https://www.baeldung.com/java-graalvm-docker-image)
|
||||
@@ -9,9 +9,10 @@
|
||||
<description>Module For Spring Boot MVC Web</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>
|
||||
|
||||
+4
-4
@@ -4,10 +4,10 @@ import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
public class HelloWorldServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
+4
-4
@@ -4,10 +4,10 @@ import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
public class SpringHelloWorldServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package com.baeldung.common.error;
|
||||
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import jakarta.servlet.Servlet;
|
||||
|
||||
public class SpringHelloServletRegistrationBean extends ServletRegistrationBean {
|
||||
|
||||
|
||||
+3
-3
@@ -4,9 +4,9 @@ import org.springframework.web.WebApplicationInitializer;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.context.support.XmlWebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRegistration;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRegistration;
|
||||
|
||||
public class WebAppInitializer implements WebApplicationInitializer {
|
||||
|
||||
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
package com.baeldung.servlets.servlets;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
package com.baeldung.servlets.servlets.javaee;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.annotation.WebServlet;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@WebServlet(name = "AnnotationServlet", description = "Example Servlet Using Annotations", urlPatterns = { "/annotationservlet" })
|
||||
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
package com.baeldung.servlets.servlets.javaee;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package com.baeldung.utils;
|
||||
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package com.baeldung.utils.controller;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
|
||||
+9
-7
@@ -1,32 +1,34 @@
|
||||
package com.baeldung.utils;
|
||||
|
||||
import com.baeldung.utils.controller.UtilsController;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import static org.mockito.MockitoAnnotations.openMocks;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
public class UtilsControllerIntegrationTest {
|
||||
class UtilsControllerIntegrationTest {
|
||||
|
||||
@InjectMocks
|
||||
private UtilsController utilsController;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
openMocks(this);
|
||||
this.mockMvc = MockMvcBuilders.standaloneSetup(utilsController).build();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenParameter_setRequestParam_andSetSessionAttribute() throws Exception {
|
||||
void givenParameter_setRequestParam_andSetSessionAttribute() throws Exception {
|
||||
String param = "testparam";
|
||||
this.mockMvc.perform(post("/setParam").param("param", param).sessionAttr("parameter", param)).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package com.baeldung.spytest;
|
||||
|
||||
public interface ExternalAlertService {
|
||||
public boolean alert(Order order);
|
||||
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.spytest;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class NotificationService {
|
||||
|
||||
private ExternalAlertService externalAlertService;
|
||||
|
||||
public void notify(Order order) {
|
||||
System.out.println(order);
|
||||
}
|
||||
|
||||
public boolean raiseAlert(Order order) {
|
||||
return externalAlertService.alert(order);
|
||||
}
|
||||
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package com.baeldung.spytest;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class Order {
|
||||
|
||||
private UUID id;
|
||||
|
||||
private String name;
|
||||
|
||||
private OrderType orderType;
|
||||
|
||||
private double orderQuantity;
|
||||
|
||||
private String address;
|
||||
|
||||
public Order(UUID id, String name, double orderQuantity, String address) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.orderQuantity = orderQuantity;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public enum OrderType {
|
||||
INDIVIDUAL, BULK;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public double getOrderQuantity() {
|
||||
return orderQuantity;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.spytest;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class OrderRepository {
|
||||
|
||||
public static final HashMap<UUID, Order> orders = new HashMap<>();
|
||||
|
||||
public Order save(Order order) {
|
||||
UUID orderId = UUID.randomUUID();
|
||||
order.setId(orderId);
|
||||
orders.put(UUID.randomUUID(), order);
|
||||
return order;
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.spytest;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class OrderService {
|
||||
|
||||
public final OrderRepository orderRepository;
|
||||
|
||||
public final NotificationService notificationService;
|
||||
|
||||
public OrderService(OrderRepository orderRepository, NotificationService notificationService) {
|
||||
this.orderRepository = orderRepository;
|
||||
this.notificationService = notificationService;
|
||||
}
|
||||
|
||||
public Order save(Order order) {
|
||||
order = orderRepository.save(order);
|
||||
notificationService.notify(order);
|
||||
if (!notificationService.raiseAlert(order)) {
|
||||
throw new RuntimeException("Alert not raised");
|
||||
}
|
||||
return order;
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.spytest;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SpyTestApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpyTestApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.baeldung.spytest;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
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.mock.mockito.SpyBean;
|
||||
|
||||
@SpringBootTest
|
||||
class OrderServiceIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
OrderRepository orderRepository;
|
||||
@SpyBean
|
||||
NotificationService notificationService;
|
||||
@SpyBean
|
||||
OrderService orderService;
|
||||
|
||||
@Test
|
||||
void givenNotificationServiceIsUsingSpyBean_whenOrderServiceIsCalled_thenNotificationServiceSpyBeanShouldBeInvoked() {
|
||||
|
||||
Order orderInput = new Order(null, "Test", 1.0, "17 St Andrews Croft, Leeds ,LS17 7TP");
|
||||
doReturn(true).when(notificationService)
|
||||
.raiseAlert(any(Order.class));
|
||||
Order order = orderService.save(orderInput);
|
||||
Assertions.assertNotNull(order);
|
||||
Assertions.assertNotNull(order.getId());
|
||||
verify(notificationService).notify(any(Order.class));
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.baeldung.spytest;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Spy;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
class OrderServiceUnitTest {
|
||||
|
||||
@Spy
|
||||
OrderRepository orderRepository;
|
||||
@Spy
|
||||
NotificationService notificationService;
|
||||
@InjectMocks
|
||||
OrderService orderService;
|
||||
|
||||
@Test
|
||||
void givenNotificationServiceIsUsingSpy_whenOrderServiceIsCalled_thenNotificationServiceSpyShouldBeInvoked() {
|
||||
|
||||
UUID orderId = UUID.randomUUID();
|
||||
Order orderInput = new Order(orderId, "Test", 1.0, "17 St Andrews Croft, Leeds ,LS17 7TP");
|
||||
doReturn(orderInput).when(orderRepository)
|
||||
.save(any());
|
||||
doReturn(true).when(notificationService)
|
||||
.raiseAlert(any(Order.class));
|
||||
Order order = orderService.save(orderInput);
|
||||
Assertions.assertNotNull(order);
|
||||
Assertions.assertEquals(orderId, order.getId());
|
||||
verify(notificationService).notify(any(Order.class));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user