Merge remote-tracking branch 'origin/PR-7005' into PR-7005
This commit is contained in:
@@ -104,6 +104,7 @@
|
||||
<module>spring-boot-springdoc-2</module>
|
||||
<module>spring-boot-documentation</module>
|
||||
<module>spring-boot-3-url-matching</module>
|
||||
<module>spring-boot-graalvm-docker</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
|
||||
@@ -41,6 +41,31 @@
|
||||
<artifactId>mockserver-netty</artifactId>
|
||||
<version>${mockserver.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>${jupiter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${jupiter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${jupiter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>${jupiter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-commons</artifactId>
|
||||
<version>1.10.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-client-java</artifactId>
|
||||
@@ -183,12 +208,50 @@
|
||||
<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>
|
||||
<spring-boot.version>3.1.0</spring-boot.version>
|
||||
<spring-boot.version>3.2.0-SNAPSHOT</spring-boot.version>
|
||||
<lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
|
||||
<jupiter.version>5.10.0</jupiter.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.baeldung.restclient;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Article {
|
||||
Integer id;
|
||||
String title;
|
||||
|
||||
public Article() {}
|
||||
|
||||
public Article(Integer id, String title) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
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;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Article article = (Article) o;
|
||||
return Objects.equals(id, article.id) && Objects.equals(title, article.title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, title);
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.baeldung.restclient;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/articles")
|
||||
public class ArticleController {
|
||||
Map<Integer, Article> database = new HashMap<>();
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<Collection<Article>> getArticles() {
|
||||
Collection<Article> values = database.values();
|
||||
if (values.isEmpty()) {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
return ResponseEntity.ok(values);
|
||||
}
|
||||
|
||||
@GetMapping("/{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
|
||||
public void createArticle(@RequestBody Article article) {
|
||||
database.put(article.getId(), article);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public void updateArticle(@PathVariable("id") Integer id, @RequestBody Article article) {
|
||||
assert Objects.equals(id, article.getId());
|
||||
database.remove(id);
|
||||
database.put(id, article);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public void deleteArticle(@PathVariable Integer id) {
|
||||
database.remove(id);
|
||||
}
|
||||
@DeleteMapping()
|
||||
public void deleteArticles() {
|
||||
database.clear();
|
||||
}
|
||||
}
|
||||
+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() {
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.restclient;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class RestClientApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(RestClientApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
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.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)
|
||||
public class RestClientIntegrationTest {
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
private String uriBase;
|
||||
RestClient restClient = RestClient.create();
|
||||
|
||||
@Autowired
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
uriBase = "http://localhost:" + port;
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void teardown() {
|
||||
restClient.delete()
|
||||
.uri(uriBase + "/articles")
|
||||
.retrieve()
|
||||
.toBodilessEntity();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGetArticlesAndReturnString() {
|
||||
String articlesAsString = restClient.get()
|
||||
.uri(uriBase + "/articles")
|
||||
.retrieve()
|
||||
.body(String.class);
|
||||
|
||||
assertThat(articlesAsString).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPostAndGetArticles() {
|
||||
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 = restClient.get()
|
||||
.uri(uriBase + "/articles")
|
||||
.retrieve()
|
||||
.body(new ParameterizedTypeReference<>() {});
|
||||
|
||||
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");
|
||||
restClient.post()
|
||||
.uri(uriBase + "/articles")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(article)
|
||||
.retrieve()
|
||||
.toBodilessEntity();
|
||||
|
||||
Article articleChanged = new Article(1, "How to use RestClient even better");
|
||||
restClient.put()
|
||||
.uri(uriBase + "/articles/1")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(articleChanged)
|
||||
.retrieve()
|
||||
.toBodilessEntity();
|
||||
|
||||
List<Article> articles = restClient.get()
|
||||
.uri(uriBase + "/articles")
|
||||
.retrieve()
|
||||
.body(new ParameterizedTypeReference<>() {});
|
||||
|
||||
assertThat(articles).isEqualTo(List.of(articleChanged));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPostAndDeleteArticles() {
|
||||
Article article = new Article(1, "How to use RestClient");
|
||||
restClient.post()
|
||||
.uri(uriBase + "/articles")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(article)
|
||||
.retrieve()
|
||||
.toBodilessEntity();
|
||||
|
||||
restClient.delete()
|
||||
.uri(uriBase + "/articles")
|
||||
.retrieve()
|
||||
.toBodilessEntity();
|
||||
|
||||
ResponseEntity<Void> entity = restClient.get()
|
||||
.uri(uriBase + "/articles")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.retrieve()
|
||||
.toBodilessEntity();
|
||||
|
||||
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())
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
<description>This is simple boot application demonstrating a custom auto-configuration</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>
|
||||
@@ -66,6 +67,13 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>com.baeldung.autoconfiguration.example.AutoconfigurationApplication</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
+4
-3
@@ -3,10 +3,10 @@ package com.baeldung.autoconfiguration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionMessage.Style;
|
||||
@@ -20,7 +20,6 @@ import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.Environment;
|
||||
@@ -31,7 +30,9 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@Configuration
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
|
||||
@AutoConfiguration
|
||||
@ConditionalOnClass(DataSource.class)
|
||||
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
|
||||
@PropertySource("classpath:mysql.properties")
|
||||
|
||||
+4
-2
@@ -1,11 +1,13 @@
|
||||
package com.baeldung.autoconfiguration.annotationprocessor;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "database")
|
||||
public class DatabaseProperties {
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package com.baeldung.autoconfiguration.example;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class MyUser {
|
||||
|
||||
-1
@@ -1 +0,0 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.baeldung.autoconfiguration.MySQLAutoconfiguration
|
||||
+1
@@ -0,0 +1 @@
|
||||
com.baeldung.autoconfiguration.MySQLAutoconfiguration
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
usemysql=local
|
||||
|
||||
mysql-hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
|
||||
mysql-hibernate.dialect=org.hibernate.dialect.MySQLDialect
|
||||
mysql-hibernate.show_sql=true
|
||||
mysql-hibernate.hbm2ddl.auto=create-drop
|
||||
@@ -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,3 @@
|
||||
FROM ubuntu:jammy
|
||||
COPY target/springboot-graalvm-docker /springboot-graalvm-docker
|
||||
CMD ["/springboot-graalvm-docker"]
|
||||
@@ -0,0 +1,2 @@
|
||||
## Relevant Articles
|
||||
- [Create a GraalVM Docker Image](https://www.baeldung.com/java-graalvm-docker-image)
|
||||
@@ -0,0 +1,41 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-3</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-3</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-boot-graalvm-docker</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<name>spring-boot-graalvm-docker</name>
|
||||
<description>Spring Boot GrralVM with Docker</description>
|
||||
<dependencies>
|
||||
<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>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.graalvm.buildtools</groupId>
|
||||
<artifactId>native-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.graalvmdockerimage;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@SpringBootApplication
|
||||
public class GraalvmDockerImageApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GraalvmDockerImageApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
class HelloController {
|
||||
|
||||
@GetMapping
|
||||
public String hello() {
|
||||
return "Hello GraalVM";
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ulisesbocchio</groupId>
|
||||
<artifactId>jasypt-spring-boot-starter</artifactId>
|
||||
<artifactId>jasypt-spring-boot-starter</artifactId>
|
||||
<version>${jasypt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -46,15 +46,7 @@
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<name>Spring Milestone</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<jasypt.version>2.0.0</jasypt.version>
|
||||
<jasypt.version>3.0.5</jasypt.version>
|
||||
</properties>
|
||||
</project>
|
||||
@@ -11,10 +11,9 @@
|
||||
<description>This is a simple application demonstrating integration between Keycloak and Spring Boot.</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
<groupId>com.baeldung.spring-boot-modules</groupId>
|
||||
<artifactId>spring-boot-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
<description>This is a simple application demonstrating integration between Keycloak and Spring Boot.</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
<groupId>com.baeldung.spring-boot-modules</groupId>
|
||||
<artifactId>spring-boot-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
<description>This is a simple application demonstrating integration between Keycloak and Spring Boot.</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
<groupId>com.baeldung.spring-boot-modules</groupId>
|
||||
<artifactId>spring-boot-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
<description>Demo project for Spring Boot Logging with Log4J2</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
<groupId>com.baeldung.spring-boot-modules</groupId>
|
||||
<artifactId>spring-boot-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -10,10 +10,9 @@
|
||||
<description>Module For Spring Boot Integration with BIRT</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
<groupId>com.baeldung.spring-boot-modules</groupId>
|
||||
<artifactId>spring-boot-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -11,7 +11,7 @@ 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
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
## Relevant Articles
|
||||
- [Securing Spring Boot 3 Applications With SSL Bundles](https://www.baeldung.com/spring-boot-security-ssl-bundles)
|
||||
@@ -0,0 +1,56 @@
|
||||
<?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>
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-3</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-3</relativePath>
|
||||
</parent>
|
||||
<artifactId>springbootsslbundles</artifactId>
|
||||
<name>spring-boot-ssl-bundles</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Module for showing usage of SSL Bundles</description>
|
||||
<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.apache.httpcomponents.client5</groupId>
|
||||
<artifactId>httpclient5-fluent</artifactId>
|
||||
<version>${apache.client5.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<apache.client5.version>5.0.3</apache.client5.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.springbootsslbundles;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.boot.ssl.SslBundles;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SSLBundlesApp {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SSLBundlesApp.class, args);
|
||||
}
|
||||
@Bean
|
||||
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {
|
||||
return restTemplateBuilder.setSslBundle(sslBundles.getBundle("secure-service")).build();
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.springbootsslbundles;
|
||||
|
||||
import org.apache.hc.client5.http.classic.HttpClient;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
|
||||
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
|
||||
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ssl.NoSuchSslBundleException;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.ssl.SslBundles;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
@Component
|
||||
public class SecureRestTemplateConfig {
|
||||
private final SSLContext sslContext;
|
||||
|
||||
@Autowired
|
||||
public SecureRestTemplateConfig(SslBundles sslBundles) throws NoSuchSslBundleException {
|
||||
SslBundle sslBundle = sslBundles.getBundle("secure-service");
|
||||
this.sslContext = sslBundle.createSslContext();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RestTemplate secureRestTemplate() {
|
||||
final SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create().setSslContext(this.sslContext).build();
|
||||
final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create().setSSLSocketFactory(sslSocketFactory).build();
|
||||
HttpClient httpClient = HttpClients.custom().setConnectionManager(cm).evictExpiredConnections().build();
|
||||
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
|
||||
return new RestTemplate(factory);
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.springbootsslbundles;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Service
|
||||
public class SecureServiceRestApi {
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
@Autowired
|
||||
public SecureServiceRestApi(RestTemplate restTemplate) {
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
public String fetchData(String dataId) {
|
||||
ResponseEntity<String> response = restTemplate.exchange(
|
||||
"https://secure-service.com/api/data/{id}",
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
String.class,
|
||||
dataId
|
||||
);
|
||||
return response.getBody();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
spring:
|
||||
ssl:
|
||||
bundle:
|
||||
jks:
|
||||
secure-service:
|
||||
key:
|
||||
alias: "secure-service"
|
||||
keystore:
|
||||
location: "classpath:keystore.p12"
|
||||
password: "FooBar"
|
||||
type: "PKCS12"
|
||||
@@ -0,0 +1,31 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,54 @@
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
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
|
||||
7NNrMLXj3PGrZ2vzKDGSAU1LzLOUrJ4m
|
||||
-----END ENCRYPTED PRIVATE KEY-----
|
||||
Binary file not shown.
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Spring SSL Bundler Demo Application</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Spring SSL Bundler Demo Application</h1>
|
||||
<p>
|
||||
This is a sample application that can be built as native executable.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.springbootsslbundles;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class SpringContextTest {
|
||||
@Test
|
||||
void contextLoads() {
|
||||
|
||||
}
|
||||
}
|
||||
+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