diff --git a/core-java-modules/core-java-11-3/pom.xml b/core-java-modules/core-java-11-3/pom.xml index cacbc9089c..9d21958cff 100644 --- a/core-java-modules/core-java-11-3/pom.xml +++ b/core-java-modules/core-java-11-3/pom.xml @@ -45,7 +45,6 @@ 11 11 - 2.16.0 2.10.1 diff --git a/core-java-modules/core-java-collections-list-5/pom.xml b/core-java-modules/core-java-collections-list-5/pom.xml index d62263eb63..8fc5062ac0 100644 --- a/core-java-modules/core-java-collections-list-5/pom.xml +++ b/core-java-modules/core-java-collections-list-5/pom.xml @@ -60,7 +60,6 @@ 1.21 2.10.1 - 2.16.0 20230618 \ No newline at end of file diff --git a/jackson-modules/jackson-polymorphic-deserialization/pom.xml b/jackson-modules/jackson-polymorphic-deserialization/pom.xml index cbf67e5013..f25268d6f8 100644 --- a/jackson-modules/jackson-polymorphic-deserialization/pom.xml +++ b/jackson-modules/jackson-polymorphic-deserialization/pom.xml @@ -36,7 +36,6 @@ - 2.16.0 0.9.11 diff --git a/jackson-simple/pom.xml b/jackson-simple/pom.xml index 900c80a5e7..08395c85a4 100644 --- a/jackson-simple/pom.xml +++ b/jackson-simple/pom.xml @@ -30,9 +30,5 @@ - - - 2.16.0 - - + \ No newline at end of file diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml index f059ec449a..e4363cce9c 100644 --- a/persistence-modules/pom.xml +++ b/persistence-modules/pom.xml @@ -80,6 +80,7 @@ spring-data-geode spring-data-jpa-annotations + spring-data-jpa-annotations-2 spring-data-jpa-crud spring-data-jpa-crud-2 spring-data-jpa-enterprise diff --git a/persistence-modules/spring-boot-persistence-3/README.md b/persistence-modules/spring-boot-persistence-3/README.md index 34bbe10dc3..fc1da55635 100644 --- a/persistence-modules/spring-boot-persistence-3/README.md +++ b/persistence-modules/spring-boot-persistence-3/README.md @@ -2,4 +2,5 @@ - [Patterns for Iterating Over Large Result Sets With Spring Data JPA](https://www.baeldung.com/spring-data-jpa-iterate-large-result-sets) - [Count the Number of Rows in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-row-count) - [A Guide to Spring AbstractRoutingDatasource](https://www.baeldung.com/spring-abstract-routing-data-source) +- [How To Use findBy() With Multiple Columns in JPA](https://www.baeldung.com/spring-data-jpa-findby-multiple-columns) - More articles: [[<-- prev]](../spring-boot-persistence-2) diff --git a/persistence-modules/spring-boot-persistence-4/pom.xml b/persistence-modules/spring-boot-persistence-4/pom.xml index acff937114..2521590f3c 100644 --- a/persistence-modules/spring-boot-persistence-4/pom.xml +++ b/persistence-modules/spring-boot-persistence-4/pom.xml @@ -55,7 +55,6 @@ com.fasterxml.jackson.core jackson-databind - ${jackson.version} org.modelmapper @@ -91,7 +90,6 @@ 17 1.0.7 3.7.0 - 2.16.0 3.2.0 1.16.1 1.18.30 diff --git a/persistence-modules/spring-data-elasticsearch/pom.xml b/persistence-modules/spring-data-elasticsearch/pom.xml index b8edae68d3..1eb627ce57 100644 --- a/persistence-modules/spring-data-elasticsearch/pom.xml +++ b/persistence-modules/spring-data-elasticsearch/pom.xml @@ -60,7 +60,6 @@ 5.1.2 8.9.0 - 2.16.0 \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-annotations-2/pom.xml b/persistence-modules/spring-data-jpa-annotations-2/pom.xml new file mode 100644 index 0000000000..306d2ed172 --- /dev/null +++ b/persistence-modules/spring-data-jpa-annotations-2/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + spring-data-jpa-annotations-2 + spring-data-jpa-annotations-2 + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-test + test + + + com.h2database + h2 + + + jakarta.persistence + jakarta.persistence-api + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-annotations-2/src/main/java/com/baeldung/datajpatest/User.java b/persistence-modules/spring-data-jpa-annotations-2/src/main/java/com/baeldung/datajpatest/User.java new file mode 100644 index 0000000000..23b9273c82 --- /dev/null +++ b/persistence-modules/spring-data-jpa-annotations-2/src/main/java/com/baeldung/datajpatest/User.java @@ -0,0 +1,42 @@ +package com.baeldung.datajpatest; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "app_user") +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String username; + private String password; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-annotations-2/src/main/java/com/baeldung/datajpatest/UserApplication.java b/persistence-modules/spring-data-jpa-annotations-2/src/main/java/com/baeldung/datajpatest/UserApplication.java new file mode 100644 index 0000000000..b58c7b2339 --- /dev/null +++ b/persistence-modules/spring-data-jpa-annotations-2/src/main/java/com/baeldung/datajpatest/UserApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.datajpatest; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class UserApplication { + + public static void main(String[] args) { + SpringApplication.run(UserApplication.class); + } +} diff --git a/persistence-modules/spring-data-jpa-annotations-2/src/main/java/com/baeldung/datajpatest/UserRepository.java b/persistence-modules/spring-data-jpa-annotations-2/src/main/java/com/baeldung/datajpatest/UserRepository.java new file mode 100644 index 0000000000..3393081203 --- /dev/null +++ b/persistence-modules/spring-data-jpa-annotations-2/src/main/java/com/baeldung/datajpatest/UserRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.datajpatest; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { + + User findByUsername(String username); +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-annotations-2/src/test/java/com/baeldung/datajpatest/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-annotations-2/src/test/java/com/baeldung/datajpatest/UserRepositoryIntegrationTest.java new file mode 100644 index 0000000000..9c933c8202 --- /dev/null +++ b/persistence-modules/spring-data-jpa-annotations-2/src/test/java/com/baeldung/datajpatest/UserRepositoryIntegrationTest.java @@ -0,0 +1,68 @@ +package com.baeldung.datajpatest; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.After; +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.autoconfigure.orm.jpa.DataJpaTest; + +@DataJpaTest +public class UserRepositoryIntegrationTest { + + @Autowired + private UserRepository userRepository; + + private User testUser; + + @BeforeEach + public void setUp() { + // Initialize test data before each test method test + testUser = new User(); + testUser.setUsername("testuser"); + testUser.setPassword("password"); + userRepository.save(testUser); + } + + @After + public void tearDown() { + // Release test data after each test method + userRepository.delete(testUser); + } + + @Test + void givenUser_whenSaved_thenCanBeFoundById() { + // Verify that the user has been saved successfully + User savedUser = userRepository.findById(testUser.getId()) + .orElse(null); + + assertNotNull(savedUser); + assertEquals(testUser.getUsername(), savedUser.getUsername()); + assertEquals(testUser.getPassword(), savedUser.getPassword()); + } + + @Test + void givenUser_whenUpdated_thenCanBeFoundByIdWithUpdatedData() { + testUser.setUsername("updatedUsername"); + userRepository.save(testUser); + + User updatedUser = userRepository.findById(testUser.getId()) + .orElse(null); + + assertNotNull(updatedUser); + assertEquals("updatedUsername", updatedUser.getUsername()); + } + + @Test + void givenUser_whenFindByUsernameCalled_thenUserIsFound() { + User foundUser = userRepository.findByUsername("testuser"); + + assertNotNull(foundUser); + assertEquals("testuser", foundUser.getUsername()); + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 030b8e1843..a8e731c795 100644 --- a/pom.xml +++ b/pom.xml @@ -1192,7 +1192,7 @@ 1.2 2.3.3 1.2 - 2.16.0 + 2.16.1 1.5 1.9.2 5.9.2 diff --git a/spring-cloud-modules/spring-cloud-gateway/pom.xml b/spring-cloud-modules/spring-cloud-gateway/pom.xml index 0287ab7588..5d0594a259 100644 --- a/spring-cloud-modules/spring-cloud-gateway/pom.xml +++ b/spring-cloud-modules/spring-cloud-gateway/pom.xml @@ -8,9 +8,10 @@ jar - com.baeldung.spring.cloud - spring-cloud-modules - 1.0.0-SNAPSHOT + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../../parent-boot-3 @@ -29,13 +30,6 @@ pom import - - org.springframework.boot - spring-boot-dependencies - ${spring-boot.version} - pom - import - @@ -67,8 +61,9 @@ ${hibernate-validator.version} - javax.validation - validation-api + jakarta.validation + jakarta.validation-api + ${jakarta.validation-api.version} org.springframework.boot @@ -109,6 +104,7 @@ org.springframework.boot spring-boot-maven-plugin + com.baeldung.springcloudgateway.introduction.IntroductionGatewayApplication org.projectlombok @@ -183,12 +179,12 @@ - - + 2023.0.0 8.0.1.Final 0.7.2 9.19 + 3.0.2 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/custompredicates/factories/GoldenCustomerRoutePredicateFactory.java b/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/custompredicates/factories/GoldenCustomerRoutePredicateFactory.java index cb5c3a0b50..cf4545fd50 100644 --- a/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/custompredicates/factories/GoldenCustomerRoutePredicateFactory.java +++ b/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/custompredicates/factories/GoldenCustomerRoutePredicateFactory.java @@ -7,7 +7,7 @@ import java.util.Arrays; import java.util.List; import java.util.function.Predicate; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; import org.springframework.http.HttpCookie; diff --git a/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/web/QuoteApi.java b/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/web/QuoteApi.java index 6d3721166c..cf81b4a99e 100644 --- a/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/web/QuoteApi.java +++ b/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/oauth/backend/web/QuoteApi.java @@ -1,6 +1,6 @@ package com.baeldung.springcloudgateway.oauth.backend.web; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; diff --git a/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/CustomFiltersLiveTest.java b/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/CustomFiltersLiveTest.java index f49f8c68b6..a34f152a86 100644 --- a/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/CustomFiltersLiveTest.java +++ b/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/CustomFiltersLiveTest.java @@ -8,7 +8,7 @@ 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.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec; diff --git a/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterLiveTest.java b/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterLiveTest.java index 8906af774e..e43d017267 100644 --- a/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterLiveTest.java +++ b/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/customfilters/gatewayapp/filters/factories/ScrubResponseGatewayFilterLiveTest.java @@ -14,7 +14,7 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; diff --git a/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/custompredicates/CustomPredicatesApplicationLiveTest.java b/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/custompredicates/CustomPredicatesApplicationLiveTest.java index d9988ceb5e..08082f7c15 100644 --- a/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/custompredicates/CustomPredicatesApplicationLiveTest.java +++ b/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/custompredicates/CustomPredicatesApplicationLiveTest.java @@ -14,7 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpStatus; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; diff --git a/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplicationLiveTest.java b/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplicationLiveTest.java index 41fe37045c..fe9d20024b 100644 --- a/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplicationLiveTest.java +++ b/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/rewrite/URLRewriteGatewayApplicationLiveTest.java @@ -13,7 +13,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; diff --git a/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/webfilters/RedisWebFilterFactoriesLiveTest.java b/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/webfilters/RedisWebFilterFactoriesLiveTest.java index a28eb68775..cf6302eb28 100644 --- a/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/webfilters/RedisWebFilterFactoriesLiveTest.java +++ b/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/webfilters/RedisWebFilterFactoriesLiveTest.java @@ -11,7 +11,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.ResponseEntity; import org.springframework.test.context.ActiveProfiles; @@ -51,9 +51,8 @@ public class RedisWebFilterFactoriesLiveTest { ResponseEntity r = restTemplate.getForEntity(url, String.class); // assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - LOGGER.info("Received: status->{}, reason->{}, remaining->{}", - r.getStatusCodeValue(), r.getStatusCode().getReasonPhrase(), - r.getHeaders().get("X-RateLimit-Remaining")); + LOGGER.info("Received: status->{}, remaining->{}", + r.getStatusCodeValue(), r.getHeaders().get("X-RateLimit-Remaining")); } @After diff --git a/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/webfilters/WebFilterFactoriesLiveTest.java b/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/webfilters/WebFilterFactoriesLiveTest.java index 67e00a42fc..0caf92c2e8 100644 --- a/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/webfilters/WebFilterFactoriesLiveTest.java +++ b/spring-cloud-modules/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/webfilters/WebFilterFactoriesLiveTest.java @@ -14,7 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; diff --git a/spring-kafka-3/README.md b/spring-kafka-3/README.md index 5250070952..2cbfeaccb0 100644 --- a/spring-kafka-3/README.md +++ b/spring-kafka-3/README.md @@ -1,3 +1,5 @@ ## Relevant Articles - [Spring Kafka Trusted Packages Feature](https://www.baeldung.com/spring-kafka-trusted-packages-feature) - [How to Catch Deserialization Errors in Spring-Kafka?](https://www.baeldung.com/spring-kafka-deserialization-errors) +- [View Kafka Headers in Java](https://www.baeldung.com/java-kafka-view-headers) +- [Understanding Kafka InstanceAlreadyExistsException in Java](https://www.baeldung.com/kafka-instancealreadyexistsexception) diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/KafkaConfig.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/KafkaConfig.java new file mode 100644 index 0000000000..6514816424 --- /dev/null +++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/KafkaConfig.java @@ -0,0 +1,47 @@ +package com.baeldung.spring.kafka.groupId; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.EnableKafka; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; +import org.springframework.kafka.listener.CommonErrorHandler; + +@EnableKafka +@Configuration +class KafkaConfig { + + @Bean + ConsumerFactory consumerFactory(@Value("${spring.kafka.bootstrap-servers:localhost:9092}") String bootstrapServers) { + Map props = new HashMap<>(); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers); + props.put(ConsumerConfig.GROUP_ID_CONFIG, "${kafka.consumer.groupId:test-consumer-group}"); + props.put(ConsumerConfig.CLIENT_ID_CONFIG, "rex"); + props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + return new DefaultKafkaConsumerFactory<>(props, new StringDeserializer(), new StringDeserializer()); + } + + @Bean + ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory(ConsumerFactory consumerFactory, + CommonErrorHandler commonErrorHandler) { + var factory = new ConcurrentKafkaListenerContainerFactory(); + factory.setConsumerFactory(consumerFactory); + factory.setCommonErrorHandler(commonErrorHandler); + return factory; + } + + @Bean + CommonErrorHandler kafkaErrorHandler() { + return new KafkaErrorHandler(); + } + +} diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/KafkaErrorHandler.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/KafkaErrorHandler.java new file mode 100644 index 0000000000..c334925141 --- /dev/null +++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/KafkaErrorHandler.java @@ -0,0 +1,30 @@ +package com.baeldung.spring.kafka.groupId; + +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.common.errors.RecordDeserializationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.kafka.listener.CommonErrorHandler; +import org.springframework.kafka.listener.MessageListenerContainer; +import org.springframework.lang.NonNull; + +class KafkaErrorHandler implements CommonErrorHandler { + + private static final Logger log = LoggerFactory.getLogger(KafkaErrorHandler.class); + + @Override + public void handleOtherException(@NonNull Exception exception, @NonNull Consumer consumer, @NonNull MessageListenerContainer container, + boolean batchListener) { + handle(exception, consumer); + } + + private void handle(Exception exception, Consumer consumer) { + log.error("Exception thrown", exception); + if (exception instanceof RecordDeserializationException ex) { + consumer.seek(ex.topicPartition(), ex.offset() + 1L); + consumer.commitSync(); + } else { + log.error("Exception not handled", exception); + } + } +} diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/Main.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/Main.java new file mode 100644 index 0000000000..589b20c68f --- /dev/null +++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/Main.java @@ -0,0 +1,14 @@ +package com.baeldung.spring.kafka.groupId; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan(basePackages = "com.baeldung.spring.kafka.groupId") +public class Main { + + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/MyKafkaConsumer.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/MyKafkaConsumer.java new file mode 100644 index 0000000000..f26b605a7b --- /dev/null +++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/MyKafkaConsumer.java @@ -0,0 +1,41 @@ +package com.baeldung.spring.kafka.groupId; + +import java.util.concurrent.CountDownLatch; + +import org.apache.kafka.clients.consumer.Consumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.messaging.handler.annotation.Payload; +import org.springframework.stereotype.Service; + +@Service +public class MyKafkaConsumer { + + private static final Logger LOGGER = LoggerFactory.getLogger(MyKafkaConsumer.class); + + private CountDownLatch latch = new CountDownLatch(1); + + private String payload; + + @KafkaListener(topics = "${kafka.topic.name:test-topic}", clientIdPrefix = "neo", groupId = "${kafka.consumer.groupId:test-consumer-group}", concurrency = "4") + public void receive(@Payload String payload, Consumer consumer) { + LOGGER.info("Consumer='{}' received payload='{}'", consumer.groupMetadata() + .memberId(), payload); + this.payload = payload; + + latch.countDown(); + } + + public CountDownLatch getLatch() { + return latch; + } + + public void resetLatch() { + latch = new CountDownLatch(1); + } + + public String getPayload() { + return payload; + } +} diff --git a/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/MyKafkaProducer.java b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/MyKafkaProducer.java new file mode 100644 index 0000000000..f8642a99a5 --- /dev/null +++ b/spring-kafka-3/src/main/java/com/baeldung/spring/kafka/groupId/MyKafkaProducer.java @@ -0,0 +1,24 @@ +package com.baeldung.spring.kafka.groupId; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Service; + +@Service +public class MyKafkaProducer { + + private static final Logger LOGGER = LoggerFactory.getLogger(MyKafkaProducer.class); + + @Value("${kafka.topic.name:test-topic}") + private String topic; + @Autowired + private KafkaTemplate kafkaTemplate; + + public void send(String payload) { + LOGGER.info("Sending payload='{}' to topic='{}'", payload, topic); + kafkaTemplate.send(topic, payload); + } +} diff --git a/spring-kafka-3/src/test/java/com/baeldung/spring/kafka/groupId/MainLiveTest.java b/spring-kafka-3/src/test/java/com/baeldung/spring/kafka/groupId/MainLiveTest.java new file mode 100644 index 0000000000..2c48d25ca2 --- /dev/null +++ b/spring-kafka-3/src/test/java/com/baeldung/spring/kafka/groupId/MainLiveTest.java @@ -0,0 +1,44 @@ +package com.baeldung.spring.kafka.groupId; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.concurrent.TimeUnit; + +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.context.annotation.ComponentScan; +import org.springframework.kafka.test.context.EmbeddedKafka; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest(classes = Main.class) +@ActiveProfiles("groupId") +@ComponentScan(basePackages = "com.baeldung.spring.kafka.groupId") +@DirtiesContext +@EmbeddedKafka(partitions = 4, topics = { "${kafka.topic.name:test-topic}" }, brokerProperties = { "listeners=PLAINTEXT://localhost:8000", "port=8000" }) +public class MainLiveTest { + + @Autowired + private MyKafkaConsumer consumer; + @Autowired + private MyKafkaProducer producer; + + @BeforeEach + void setup() { + consumer.resetLatch(); + } + + @Test + public void givenEmbeddedKafkaBroker_whenSendingWithSimpleProducer_thenMessageReceived() throws Exception { + String data = "Test 123..."; + producer.send(data); + boolean messageConsumed = consumer.getLatch() + .await(10, TimeUnit.SECONDS); + assertTrue(messageConsumed); + assertThat(consumer.getPayload(), containsString(data)); + } +} diff --git a/spring-kafka-3/src/test/resources/application-groupId.properties b/spring-kafka-3/src/test/resources/application-groupId.properties new file mode 100644 index 0000000000..648ae1b603 --- /dev/null +++ b/spring-kafka-3/src/test/resources/application-groupId.properties @@ -0,0 +1 @@ +spring.kafka.bootstrap-servers=localhost:8000 diff --git a/spring-security-modules/spring-security-ldap/pom.xml b/spring-security-modules/spring-security-ldap/pom.xml index 9f4f3b4106..0da7fc27c5 100644 --- a/spring-security-modules/spring-security-ldap/pom.xml +++ b/spring-security-modules/spring-security-ldap/pom.xml @@ -10,8 +10,9 @@ com.baeldung - spring-security-modules + parent-boot-3 0.0.1-SNAPSHOT + ../../parent-boot-3 @@ -64,6 +65,11 @@ + + com.unboundid + unboundid-ldapsdk + ${unboundid-ldapsdk.version} + @@ -78,6 +84,8 @@ 1.5.5 + com.baeldung.SampleLDAPApplication + 4.0.10 \ No newline at end of file diff --git a/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/SampleLDAPApplication.java b/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/SampleLDAPApplication.java index 2d619cccfa..af1dd350a8 100644 --- a/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/SampleLDAPApplication.java +++ b/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/SampleLDAPApplication.java @@ -3,9 +3,6 @@ package com.baeldung; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.annotation.Bean; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * Main Application Class - uses Spring Boot. Just run this as a normal Java diff --git a/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/config/SecurityConfig.java b/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/config/SecurityConfig.java index 78e4dff29c..b76b1d945b 100644 --- a/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/config/SecurityConfig.java +++ b/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/config/SecurityConfig.java @@ -6,7 +6,7 @@ import org.springframework.ldap.core.support.BaseLdapPathContextSource; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.ldap.LdapBindAuthenticationManagerFactory; -import org.springframework.security.ldap.server.ApacheDSContainer; +import org.springframework.security.ldap.server.UnboundIdContainer; import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator; import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator; import org.springframework.security.web.SecurityFilterChain; @@ -19,8 +19,8 @@ import org.springframework.security.web.SecurityFilterChain; public class SecurityConfig { @Bean - ApacheDSContainer ldapContainer() throws Exception { - return new ApacheDSContainer("dc=baeldung,dc=com", "classpath:users.ldif"); + UnboundIdContainer ldapContainer() throws Exception { + return new UnboundIdContainer("dc=baeldung,dc=com", "classpath:users.ldif"); } @Bean @@ -41,18 +41,13 @@ public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.authorizeRequests() - .antMatchers("/", "/home", "/css/**") - .permitAll() - .anyRequest() - .authenticated() - .and() - .formLogin() - .loginPage("/login") - .permitAll() - .and() - .logout() - .logoutSuccessUrl("/"); - return http.build(); + return http.authorizeHttpRequests(auth -> auth + .requestMatchers("/", "/home", "/css/**") + .permitAll() + .anyRequest() + .authenticated()) + .formLogin(httpSecurityFormLoginConfigurer -> + httpSecurityFormLoginConfigurer.loginPage("/login").permitAll()) + .logout(logout -> logout.logoutSuccessUrl("/")).build(); } } diff --git a/spring-security-modules/spring-security-ldap/src/main/java/org/apache/directory/server/core/avltree/ArrayMarshaller.java b/spring-security-modules/spring-security-ldap/src/main/java/org/apache/directory/server/core/avltree/ArrayMarshaller.java new file mode 100644 index 0000000000..78c1e69ee7 --- /dev/null +++ b/spring-security-modules/spring-security-ldap/src/main/java/org/apache/directory/server/core/avltree/ArrayMarshaller.java @@ -0,0 +1,172 @@ +/* + * Copyright 2002-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.directory.server.core.avltree; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.Comparator; +import org.apache.directory.shared.ldap.util.StringTools; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class to serialize the Array data. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ +@SuppressWarnings("unchecked") +public class ArrayMarshaller implements Marshaller> { + + /** static logger */ + private static final Logger LOG = LoggerFactory.getLogger(ArrayMarshaller.class); + + /** used for serialized form of an empty AvlTree */ + private static final byte[] EMPTY_TREE = new byte[1]; + + /** marshaller to be used for marshalling the keys */ + private Marshaller keyMarshaller; + + /** key Comparator for the AvlTree */ + private Comparator comparator; + + /** + * Creates a new instance of AvlTreeMarshaller with a custom key Marshaller. + * @param comparator Comparator to be used for key comparision + * @param keyMarshaller marshaller for keys + */ + public ArrayMarshaller(Comparator comparator, Marshaller keyMarshaller) { + this.comparator = comparator; + this.keyMarshaller = keyMarshaller; + } + + /** + * Creates a new instance of AvlTreeMarshaller with the default key Marshaller which + * uses Java Serialization. + * @param comparator Comparator to be used for key comparision + */ + public ArrayMarshaller(Comparator comparator) { + this.comparator = comparator; + this.keyMarshaller = (Marshaller) DefaultMarshaller.INSTANCE; + } + + /** + * Marshals the given tree to bytes + * @param tree the tree to be marshalled + */ + public byte[] serialize(ArrayTree tree) { + if ((tree == null) || (tree.size() == 0)) { + return EMPTY_TREE; + } + + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + DataOutputStream out = new DataOutputStream(byteStream); + byte[] data = null; + + try { + out.writeByte(0); // represents the start of an Array byte stream + out.writeInt(tree.size()); + + for (int position = 0; position < tree.size(); position++) { + E value = tree.get(position); + byte[] bytes = this.keyMarshaller.serialize(value); + + // Write the key length + out.writeInt(bytes.length); + + // Write the key if its length is not null + if (bytes.length != 0) { + out.write(bytes); + } + } + + out.flush(); + data = byteStream.toByteArray(); + + // Try to deserialize, just to see + try { + deserialize(data); + } + catch (NullPointerException npe) { + System.out.println("Bad serialization, tree : [" + StringTools.dumpBytes(data) + "]"); + throw npe; + } + + out.close(); + } + catch (IOException ex) { + ex.printStackTrace(); + } + + return data; + } + + /** + * Creates an Array from given bytes of data. + * @param data byte array to be converted into an array + */ + public ArrayTree deserialize(byte[] data) throws IOException { + try { + if ((data == null) || (data.length == 0)) { + throw new IOException("Null or empty data array is invalid."); + } + + if ((data.length == 1) && (data[0] == 0)) { + E[] array = (E[]) new Object[] {}; + ArrayTree tree = new ArrayTree(this.comparator, array); + return tree; + } + + ByteArrayInputStream bin = new ByteArrayInputStream(data); + DataInputStream din = new DataInputStream(bin); + + byte startByte = din.readByte(); + + if (startByte != 0) { + throw new IOException("wrong array serialized data format"); + } + + int size = din.readInt(); + E[] nodes = (E[]) new Object[size]; + + for (int i = 0; i < size; i++) { + // Read the object's size + int dataSize = din.readInt(); + + if (dataSize != 0) { + byte[] bytes = new byte[dataSize]; + + din.read(bytes); + E key = this.keyMarshaller.deserialize(bytes); + nodes[i] = key; + } + } + + ArrayTree arrayTree = new ArrayTree(this.comparator, nodes); + + return arrayTree; + } + catch (NullPointerException npe) { + System.out.println("Bad tree : [" + StringTools.dumpBytes(data) + "]"); + throw npe; + } + } + +} \ No newline at end of file diff --git a/testing-modules/instancio/pom.xml b/testing-modules/instancio/pom.xml index 7687ce282d..2cc1a84748 100644 --- a/testing-modules/instancio/pom.xml +++ b/testing-modules/instancio/pom.xml @@ -52,7 +52,6 @@ 2.9.0 - 2.14.1 5.9.2 diff --git a/testing-modules/mocks-2/pom.xml b/testing-modules/mocks-2/pom.xml index 2ef1a03dff..9db598421e 100644 --- a/testing-modules/mocks-2/pom.xml +++ b/testing-modules/mocks-2/pom.xml @@ -33,7 +33,6 @@ 1.6.0 - 2.16.0 5.3.25 diff --git a/testing-modules/spring-testing/pom.xml b/testing-modules/spring-testing/pom.xml index c4c929b7aa..665ac305a0 100644 --- a/testing-modules/spring-testing/pom.xml +++ b/testing-modules/spring-testing/pom.xml @@ -3,18 +3,18 @@ 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"> 4.0.0 + com.baeldung spring-testing 0.1-SNAPSHOT spring-testing - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 - - + + ch.qos.logback + logback-classic + 1.5.0 + test + org.hamcrest java-hamcrest @@ -23,29 +23,66 @@ org.projectlombok lombok - ${lombok.version} + 1.18.30 provided org.springframework.boot spring-boot-starter + 3.2.2 + + + org.springframework.boot + spring-boot-starter-logging + + - org.springframework.boot - spring-boot-starter-test - test + spring-boot + 3.2.2 + + + org.springframework.data + spring-data-jpa + 3.2.2 + + + org.springframework.data + spring-data-commons + 3.2.2 + + + org.springframework + spring-beans + ${spring.version} org.springframework spring-core ${spring.version} + compile org.springframework spring-context ${spring.version} + + org.springframework + spring-expression + ${spring.version} + + + org.springframework + spring-test + ${spring.version} + + + org.springframework + spring-web + ${spring.version} + org.springframework spring-webmvc @@ -56,10 +93,6 @@ javax.persistence ${javax.persistence.version} - - org.springframework.data - spring-data-jpa - org.awaitility awaitility @@ -67,9 +100,34 @@ test - javax.servlet - javax.servlet-api - ${javax.servlet-api.version} + jakarta.servlet + jakarta.servlet-api + 6.0.0 + + + + org.springframework.boot + spring-boot-starter-test + test + 3.2.2 + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.junit.jupiter + junit-jupiter + 5.9.2 + test + + + org.junit.vintage + junit-vintage-engine + 5.9.2 + test diff --git a/testing-modules/spring-testing/src/main/java/com/baeldung/config/WebConfig.java b/testing-modules/spring-testing/src/main/java/com/baeldung/config/WebConfig.java index eca0aed57f..3ccd8b94da 100644 --- a/testing-modules/spring-testing/src/main/java/com/baeldung/config/WebConfig.java +++ b/testing-modules/spring-testing/src/main/java/com/baeldung/config/WebConfig.java @@ -5,7 +5,7 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import javax.servlet.ServletContext; +import jakarta.servlet.ServletContext; @EnableWebMvc @Configuration diff --git a/testing-modules/spring-testing/src/test/resources/logback-spring.xml b/testing-modules/spring-testing/src/test/resources/logback-spring.xml new file mode 100644 index 0000000000..6636929220 --- /dev/null +++ b/testing-modules/spring-testing/src/test/resources/logback-spring.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file