From 73c2c6bc6737fcd788025c9b446aef4371a178e4 Mon Sep 17 00:00:00 2001 From: technoddy Date: Sun, 19 Mar 2023 13:32:11 -0400 Subject: [PATCH 01/40] Creating shallow copy vs deep copy in Java --- .../baeldung/shallowvsdeepcopy/Address.java | 58 +++++++++++++++++++ .../shallowvsdeepcopy/UserWithDeepClone.java | 49 ++++++++++++++++ .../UserWithShallowClone.java | 48 +++++++++++++++ .../shallowvsdeepcopy/UserCloneUnitTest.java | 23 ++++++++ 4 files changed, 178 insertions(+) create mode 100644 core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/Address.java create mode 100644 core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithDeepClone.java create mode 100644 core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithShallowClone.java create mode 100644 core-java-modules/core-java-lang-oop-patterns/src/test/java/com/baeldung/shallowvsdeepcopy/UserCloneUnitTest.java diff --git a/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/Address.java b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/Address.java new file mode 100644 index 0000000000..a31e8d7e2d --- /dev/null +++ b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/Address.java @@ -0,0 +1,58 @@ +package com.baeldung.shallowvsdeepcopy; + +class Address implements Cloneable{ + + private String streetName; + private String zipCode; + private String cityName; + private String country; + + public Address(String streetName, String zipCode, String cityName, String country) { + this.streetName = streetName; + this.zipCode = zipCode; + this.cityName = cityName; + this.country = country; + } + + public String getStreetName() { + return streetName; + } + + public void setStreetName(String streetName) { + this.streetName = streetName; + } + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + public String getCityName() { + return cityName; + } + + public void setCityName(String cityName) { + this.cityName = cityName; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + @Override + public Address clone() { + try { + Address clone = (Address) super.clone(); + return clone; + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithDeepClone.java b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithDeepClone.java new file mode 100644 index 0000000000..70646d396c --- /dev/null +++ b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithDeepClone.java @@ -0,0 +1,49 @@ +package com.baeldung.shallowvsdeepcopy; + +public class UserWithDeepClone implements Cloneable{ + + private String name; + private Address address; + private int age; + + public UserWithDeepClone(String name, Address address, int age) { + this.name = name; + this.address = address; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public UserWithDeepClone clone() { + try { + UserWithDeepClone clone = (UserWithDeepClone) super.clone(); + clone.setAddress(clone.getAddress().clone()); + return clone; + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithShallowClone.java b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithShallowClone.java new file mode 100644 index 0000000000..19c9b55412 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithShallowClone.java @@ -0,0 +1,48 @@ +package com.baeldung.shallowvsdeepcopy; + +public class UserWithShallowClone implements Cloneable{ + + private String name; + private Address address; + private int age; + + public UserWithShallowClone(String name, Address address, int age) { + this.name = name; + this.address = address; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public UserWithShallowClone clone() { + try { + UserWithShallowClone clone = (UserWithShallowClone) super.clone(); + return clone; + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-patterns/src/test/java/com/baeldung/shallowvsdeepcopy/UserCloneUnitTest.java b/core-java-modules/core-java-lang-oop-patterns/src/test/java/com/baeldung/shallowvsdeepcopy/UserCloneUnitTest.java new file mode 100644 index 0000000000..f5a7d9df93 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-patterns/src/test/java/com/baeldung/shallowvsdeepcopy/UserCloneUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.shallowvsdeepcopy; +import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class UserCloneUnitTest { + + @Test + public void givenUser_WhenCopyCreated_thenCopyIsShallow(){ + Address address = new Address("abc", "444-0000", "pqr", "USA"); + UserWithShallowClone user = new UserWithShallowClone("baeldung", address,32); + + UserWithShallowClone userClone = (UserWithShallowClone)user.clone(); + assertThat(userClone.getAddress()).isEqualTo(user.getAddress()); + } + + @Test + public void givenUserWithDeepCloneMethod_WhenCopyCreated_thenCopyIsDeep(){ + Address address = new Address("abc", "444-0000", "pqr", "USA"); + UserWithDeepClone user = new UserWithDeepClone("baeldung", address,32); + UserWithDeepClone userClone = (UserWithDeepClone)user.clone(); + assertThat(userClone.getAddress()).isNotEqualTo(user.getAddress()); + } +} \ No newline at end of file From 00028b8b19ed41f7d7afc473e8138e1c97ef26ce Mon Sep 17 00:00:00 2001 From: Kingsley Amankwah Date: Fri, 21 Apr 2023 04:48:52 +0530 Subject: [PATCH 02/40] JPA/Hibernate Associations --- .../baeldung/association/Bidirectional.java | 40 ++++++++ .../baeldung/association/Unidirectional.java | 92 ++++++++++++++++++ .../association/BidirectionalUnitTest.java | 48 +++++++++ .../association/UnidirectionalUnitTest.java | 97 +++++++++++++++++++ 4 files changed, 277 insertions(+) create mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Bidirectional.java create mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Unidirectional.java create mode 100644 persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/BidirectionalUnitTest.java create mode 100644 persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/UnidirectionalUnitTest.java diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Bidirectional.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Bidirectional.java new file mode 100644 index 0000000000..aff5feaeba --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Bidirectional.java @@ -0,0 +1,40 @@ +package com.baeldung.association; + +import java.util.List; +import javax.persistence.*; + +@Entity +public class Department { + + @OneToMany(mappedBy = "department") + private List employees; + +} + +@Entity +public class Employee { + + @ManyToOne + @JoinColumn(name = "department_id") + private Department department; + +} + +@Entity +public class Student { + + @ManyToMany(mappedBy = "students") + private List courses; + +} + +@Entity +public class Course { + + @ManyToMany + @JoinTable(name = "course_student", + joinColumns = @JoinColumn(name = "course_id"), + inverseJoinColumns = @JoinColumn(name = "student_id")) + private List students; + +} diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Unidirectional.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Unidirectional.java new file mode 100644 index 0000000000..3e60b8bdd3 --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Unidirectional.java @@ -0,0 +1,92 @@ +package com.baeldung.association; + +import javax.persistence.*; + +import java.util.List; +import java.util.Set; + +@Entity +public class Department { + + @Id + private Long id; + + @OneToMany + @JoinColumn(name = "department_id") + private List employees; + +} + +@Entity +public class Employee { + + @Id + private Long id; + + @OneToOne + @JoinColumn(name = "parking_spot_id") + private ParkingSpot parkingSpot; + +} + +@Entity +public class ParkingSpot { + + @Id + private Long id; + +} + +@Entity +public class Student { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + @ManyToOne + @JoinColumn(name = "course_id") + private Course course; + +} + +@Entity +public class Course { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + +} + +@Entity +public class Book { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String title; + + @ManyToMany + @JoinTable(name = "book_author", + joinColumns = @JoinColumn(name = "book_id"), + inverseJoinColumns = @JoinColumn(name = "author_id")) + private Set authors; + +} + +@Entity +public class Author { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + +} diff --git a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/BidirectionalUnitTest.java b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/BidirectionalUnitTest.java new file mode 100644 index 0000000000..99d33af12d --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/BidirectionalUnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.association; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +public class BidirectionalUnitTest { + + @Test + public void givenDepartmentWithEmployees_whenGetEmployees_thenReturnListWithEmployees() { + // given + Department department = new Department(); + Employee employee1 = new Employee(); + Employee employee2 = new Employee(); + department.getEmployees().add(employee1); + department.getEmployees().add(employee2); + + // when + List result = department.getEmployees(); + + // then + assertAll("department employees", + () -> assertEquals(2, result.size()), + () -> assertTrue(result.contains(employee1)), + () -> assertTrue(result.contains(employee2)) + ); + } + + @Test + public void givenCourseWithStudents_whenGetStudents_thenReturnListWithStudents() { + // given + Course course = new Course(); + Student student1 = new Student(); + Student student2 = new Student(); + course.getStudents().add(student1); + course.getStudents().add(student2); + + // when + List result = course.getStudents(); + + // then + assertAll("course students", + () -> assertEquals(2, result.size()), + () -> assertTrue(result.contains(student1)), + () -> assertTrue(result.contains(student2)) + ); + } + +} diff --git a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/UnidirectionalUnitTest.java b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/UnidirectionalUnitTest.java new file mode 100644 index 0000000000..880832c163 --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/UnidirectionalUnitTest.java @@ -0,0 +1,97 @@ +package com.baeldung.association; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaTest +public class UnidirectionalUnitTest { + + private final TestEntityManager entityManager; + + public UnidirectionalUnitTest(TestEntityManager entityManager) { + this.entityManager = entityManager; + } + + @Test + public void givenDepartmentWithEmployees_whenFindById_thenDepartmentWithEmployeesReturned() { + // given + Employee employee1 = new Employee(); + Employee employee2 = new Employee(); + Department department = new Department(); + department.setEmployees(List.of(employee1, employee2)); + entityManager.persist(department); + entityManager.flush(); + + // when + Department foundDepartment = entityManager.find(Department.class, department.getId()); + + // then + assertThat(foundDepartment).isEqualTo(department); + assertThat(foundDepartment.getEmployees()).containsExactly(employee1, employee2); + } + + @Test + public void givenStudentWithCourse_whenFindById_thenStudentWithCourseReturned() { + // given + Course course = new Course(); + entityManager.persist(course); + entityManager.flush(); + Student student = new Student(); + student.setCourse(course); + entityManager.persist(student); + entityManager.flush(); + + // when + Student foundStudent = entityManager.find(Student.class, student.getId()); + + // then + assertThat(foundStudent).isEqualTo(student); + assertThat(foundStudent.getCourse()).isEqualTo(course); + } + + @Test + public void givenEmployeeWithParkingSpot_whenFindById_thenEmployeeWithParkingSpotReturned() { + // given + ParkingSpot parkingSpot = new ParkingSpot(); + entityManager.persist(parkingSpot); + entityManager.flush(); + Employee employee = new Employee(); + employee.setParkingSpot(parkingSpot); + entityManager.persist(employee); + entityManager.flush(); + + // when + Employee foundEmployee = entityManager.find(Employee.class, employee.getId()); + + // then + assertThat(foundEmployee).isEqualTo(employee); + assertThat(foundEmployee.getParkingSpot()).isEqualTo(parkingSpot); + } + + @Test + public void givenBookWithAuthors_whenFindById_thenBookWithAuthorsReturned() { + // given + Author author1 = new Author(); + Author author2 = new Author(); + entityManager.persist(author1); + entityManager.persist(author2); + entityManager.flush(); + Book book = new Book(); + book.setAuthors(Set.of(author1, author2)); + entityManager.persist(book); + entityManager.flush(); + + // when + Book foundBook = entityManager.find(Book.class, book.getId()); + + // then + assertThat(foundBook).isEqualTo(book); + assertThat(foundBook.getAuthors()).containsExactly(author1, author2); + } + +} From 82f9d6a50060568bbe679c12223324b074fa5427 Mon Sep 17 00:00:00 2001 From: Kingsley Amankwah Date: Thu, 27 Apr 2023 05:00:38 +0530 Subject: [PATCH 03/40] Hibernate Associations --- .../main/java/com/baeldung/HibernateUtil.java | 2 + .../baeldung/association/Bidirectional.java | 40 ------ .../baeldung/association/Unidirectional.java | 92 ------------- .../associations/biredirectional/Course.java | 24 ++++ .../biredirectional/Department.java | 21 +++ .../biredirectional/Employee.java | 19 +++ .../associations/biredirectional/Student.java | 20 +++ .../associations/unidirectional/Author.java | 17 +++ .../associations/unidirectional/Book.java | 20 +++ .../unidirectional/Department.java | 33 +++++ .../associations/unidirectional/Employee.java | 42 ++++++ .../unidirectional/ParkingSpot.java | 11 ++ .../association/BidirectionalUnitTest.java | 48 ------- .../association/UnidirectionalUnitTest.java | 97 ------------- .../associations/BidirectionalUnitTest.java | 103 ++++++++++++++ .../hibernate/associations/DataJpaTest.java | 5 + .../associations/UnidirectionalUnitTest.java | 128 ++++++++++++++++++ 17 files changed, 445 insertions(+), 277 deletions(-) delete mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Bidirectional.java delete mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Unidirectional.java create mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Course.java create mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Department.java create mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Employee.java create mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Student.java create mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Author.java create mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Book.java create mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Department.java create mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Employee.java create mode 100644 persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/ParkingSpot.java delete mode 100644 persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/BidirectionalUnitTest.java delete mode 100644 persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/UnidirectionalUnitTest.java create mode 100644 persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/BidirectionalUnitTest.java create mode 100644 persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/DataJpaTest.java create mode 100644 persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/UnidirectionalUnitTest.java diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/HibernateUtil.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/HibernateUtil.java index 26ad7e77ba..8af6b12bae 100644 --- a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/HibernateUtil.java +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/HibernateUtil.java @@ -7,6 +7,7 @@ import org.hibernate.service.ServiceRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +// import com.baeldung.associations.unidirectional.Department; import com.baeldung.manytomany.model.Employee; import com.baeldung.manytomany.model.Project; import com.baeldung.uuids.WebSiteUser; @@ -29,6 +30,7 @@ public class HibernateUtil { configuration.addAnnotatedClass(Element.class); configuration.addAnnotatedClass(Reservation.class); configuration.addAnnotatedClass(Sale.class); + // configuration.addAnnotatedClass(Department.class); configuration.configure("manytomany.cfg.xml"); LOGGER.debug("Hibernate Annotation Configuration loaded"); diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Bidirectional.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Bidirectional.java deleted file mode 100644 index aff5feaeba..0000000000 --- a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Bidirectional.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.baeldung.association; - -import java.util.List; -import javax.persistence.*; - -@Entity -public class Department { - - @OneToMany(mappedBy = "department") - private List employees; - -} - -@Entity -public class Employee { - - @ManyToOne - @JoinColumn(name = "department_id") - private Department department; - -} - -@Entity -public class Student { - - @ManyToMany(mappedBy = "students") - private List courses; - -} - -@Entity -public class Course { - - @ManyToMany - @JoinTable(name = "course_student", - joinColumns = @JoinColumn(name = "course_id"), - inverseJoinColumns = @JoinColumn(name = "student_id")) - private List students; - -} diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Unidirectional.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Unidirectional.java deleted file mode 100644 index 3e60b8bdd3..0000000000 --- a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/association/Unidirectional.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.baeldung.association; - -import javax.persistence.*; - -import java.util.List; -import java.util.Set; - -@Entity -public class Department { - - @Id - private Long id; - - @OneToMany - @JoinColumn(name = "department_id") - private List employees; - -} - -@Entity -public class Employee { - - @Id - private Long id; - - @OneToOne - @JoinColumn(name = "parking_spot_id") - private ParkingSpot parkingSpot; - -} - -@Entity -public class ParkingSpot { - - @Id - private Long id; - -} - -@Entity -public class Student { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - private String name; - - @ManyToOne - @JoinColumn(name = "course_id") - private Course course; - -} - -@Entity -public class Course { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - private String name; - -} - -@Entity -public class Book { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - private String title; - - @ManyToMany - @JoinTable(name = "book_author", - joinColumns = @JoinColumn(name = "book_id"), - inverseJoinColumns = @JoinColumn(name = "author_id")) - private Set authors; - -} - -@Entity -public class Author { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - private String name; - -} diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Course.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Course.java new file mode 100644 index 0000000000..aadc08c090 --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Course.java @@ -0,0 +1,24 @@ +package com.baeldung.associations.biredirectional; +import jakarta.persistence.*; +import java.util.List; + +@Entity +public class Course { + + @Id + private Long id; + + private String name; + + @ManyToMany + @JoinTable(name = "course_student", + joinColumns = @JoinColumn(name = "course_id"), + inverseJoinColumns = @JoinColumn(name = "student_id")) + private List students; + + public List getStudents() { + return students; + } + + //getters and setters +} diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Department.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Department.java new file mode 100644 index 0000000000..23f56ccd47 --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Department.java @@ -0,0 +1,21 @@ +package com.baeldung.associations.biredirectional; + +import java.util.List; +import jakarta.persistence.*; + + +@Entity +public class Department { + + @Id + private Long id; + + @OneToMany(mappedBy = "department") + private List employees; + + public List getEmployees() { + return employees; + } + + +} diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Employee.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Employee.java new file mode 100644 index 0000000000..92514b9b8c --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Employee.java @@ -0,0 +1,19 @@ +package com.baeldung.associations.biredirectional; + +import jakarta.persistence.*; + + +@Entity +public class Employee { + + @Id + private Long id; + + private String name; + + @ManyToOne + @JoinColumn(name = "department_id") + private Department department; + + //getters and setters +} diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Student.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Student.java new file mode 100644 index 0000000000..a494f2475f --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Student.java @@ -0,0 +1,20 @@ +package com.baeldung.associations.biredirectional; + +import java.util.List; + +import jakarta.persistence.*; + +@Entity +public class Student { + + @Id + private Long id; + + private String name; + + @ManyToMany(mappedBy = "students") + private List courses; + + // getters and setters +} + diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Author.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Author.java new file mode 100644 index 0000000000..6a106071a1 --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Author.java @@ -0,0 +1,17 @@ +package com.baeldung.associations.unidirectional; +import jakarta.persistence.*; +import java.util.Set; + +@Entity +public class Author { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + @ManyToMany(fetch = FetchType.LAZY, mappedBy = "authors") + private Set books; + +} diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Book.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Book.java new file mode 100644 index 0000000000..1467a819a0 --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Book.java @@ -0,0 +1,20 @@ +package com.baeldung.associations.unidirectional; +import jakarta.persistence.*; +import java.util.Set; + +@Entity +public class Book { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String title; + + @ManyToMany(fetch = FetchType.LAZY) + @JoinTable(name = "book_author", + joinColumns = @JoinColumn(name = "book_id"), + inverseJoinColumns = @JoinColumn(name = "author_id")) + private Set authors; + +} diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Department.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Department.java new file mode 100644 index 0000000000..3d65f2e3ef --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Department.java @@ -0,0 +1,33 @@ +package com.baeldung.associations.unidirectional; + +import jakarta.persistence.*; +import java.util.List; + +@Entity +public class Department { + + @Id + private Long id; + + @OneToMany(fetch = FetchType.LAZY) + @JoinColumn(name = "department_id") + private List employees; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public List getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } +} + + diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Employee.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Employee.java new file mode 100644 index 0000000000..c9fa2c7483 --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Employee.java @@ -0,0 +1,42 @@ +package com.baeldung.associations.unidirectional; +import jakarta.persistence.*; + +@Entity +public class Employee { + + @Id + private Long id; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "parking_spot_id") + private ParkingSpot parkingSpot; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "department_id") + private Department department; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public ParkingSpot getParkingSpot() { + return parkingSpot; + } + + public void setParkingSpot(ParkingSpot parkingSpot) { + this.parkingSpot = parkingSpot; + } + + public Department getDepartment() { + return department; + } + + public void setDepartment(Department department) { + this.department = department; + } +} + diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/ParkingSpot.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/ParkingSpot.java new file mode 100644 index 0000000000..6495d895eb --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/ParkingSpot.java @@ -0,0 +1,11 @@ +package com.baeldung.associations.unidirectional; + +import jakarta.persistence.*; + +@Entity +public class ParkingSpot { + + @Id + private Long id; + +} diff --git a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/BidirectionalUnitTest.java b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/BidirectionalUnitTest.java deleted file mode 100644 index 99d33af12d..0000000000 --- a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/BidirectionalUnitTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.association; - -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - -public class BidirectionalUnitTest { - - @Test - public void givenDepartmentWithEmployees_whenGetEmployees_thenReturnListWithEmployees() { - // given - Department department = new Department(); - Employee employee1 = new Employee(); - Employee employee2 = new Employee(); - department.getEmployees().add(employee1); - department.getEmployees().add(employee2); - - // when - List result = department.getEmployees(); - - // then - assertAll("department employees", - () -> assertEquals(2, result.size()), - () -> assertTrue(result.contains(employee1)), - () -> assertTrue(result.contains(employee2)) - ); - } - - @Test - public void givenCourseWithStudents_whenGetStudents_thenReturnListWithStudents() { - // given - Course course = new Course(); - Student student1 = new Student(); - Student student2 = new Student(); - course.getStudents().add(student1); - course.getStudents().add(student2); - - // when - List result = course.getStudents(); - - // then - assertAll("course students", - () -> assertEquals(2, result.size()), - () -> assertTrue(result.contains(student1)), - () -> assertTrue(result.contains(student2)) - ); - } - -} diff --git a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/UnidirectionalUnitTest.java b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/UnidirectionalUnitTest.java deleted file mode 100644 index 880832c163..0000000000 --- a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/association/UnidirectionalUnitTest.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.baeldung.association; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -@DataJpaTest -public class UnidirectionalUnitTest { - - private final TestEntityManager entityManager; - - public UnidirectionalUnitTest(TestEntityManager entityManager) { - this.entityManager = entityManager; - } - - @Test - public void givenDepartmentWithEmployees_whenFindById_thenDepartmentWithEmployeesReturned() { - // given - Employee employee1 = new Employee(); - Employee employee2 = new Employee(); - Department department = new Department(); - department.setEmployees(List.of(employee1, employee2)); - entityManager.persist(department); - entityManager.flush(); - - // when - Department foundDepartment = entityManager.find(Department.class, department.getId()); - - // then - assertThat(foundDepartment).isEqualTo(department); - assertThat(foundDepartment.getEmployees()).containsExactly(employee1, employee2); - } - - @Test - public void givenStudentWithCourse_whenFindById_thenStudentWithCourseReturned() { - // given - Course course = new Course(); - entityManager.persist(course); - entityManager.flush(); - Student student = new Student(); - student.setCourse(course); - entityManager.persist(student); - entityManager.flush(); - - // when - Student foundStudent = entityManager.find(Student.class, student.getId()); - - // then - assertThat(foundStudent).isEqualTo(student); - assertThat(foundStudent.getCourse()).isEqualTo(course); - } - - @Test - public void givenEmployeeWithParkingSpot_whenFindById_thenEmployeeWithParkingSpotReturned() { - // given - ParkingSpot parkingSpot = new ParkingSpot(); - entityManager.persist(parkingSpot); - entityManager.flush(); - Employee employee = new Employee(); - employee.setParkingSpot(parkingSpot); - entityManager.persist(employee); - entityManager.flush(); - - // when - Employee foundEmployee = entityManager.find(Employee.class, employee.getId()); - - // then - assertThat(foundEmployee).isEqualTo(employee); - assertThat(foundEmployee.getParkingSpot()).isEqualTo(parkingSpot); - } - - @Test - public void givenBookWithAuthors_whenFindById_thenBookWithAuthorsReturned() { - // given - Author author1 = new Author(); - Author author2 = new Author(); - entityManager.persist(author1); - entityManager.persist(author2); - entityManager.flush(); - Book book = new Book(); - book.setAuthors(Set.of(author1, author2)); - entityManager.persist(book); - entityManager.flush(); - - // when - Book foundBook = entityManager.find(Book.class, book.getId()); - - // then - assertThat(foundBook).isEqualTo(book); - assertThat(foundBook.getAuthors()).containsExactly(author1, author2); - } - -} diff --git a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/BidirectionalUnitTest.java b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/BidirectionalUnitTest.java new file mode 100644 index 0000000000..5b7e01bff1 --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/BidirectionalUnitTest.java @@ -0,0 +1,103 @@ +// package com.baeldung.hibernate.associations; + +// import org.junit.jupiter.api.Test; +// import org.junit.jupiter.api.extension.ExtendWith; +// import org.springframework.beans.factory.annotation.Autowired; +// import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +// import org.springframework.test.context.junit.jupiter.SpringExtension; + +// import java.util.Arrays; +// import java.util.List; +// import com.baeldung.associations.biredirectional.*; + + +// import static org.assertj.core.api.Assertions.assertThat; + +// @ExtendWith(SpringExtension.class) +// @DataJpaTest +// public class BidirectionalHibernateIntegrationTest { + +// @Autowired +// private Course courseRepository; + +// @Autowired +// private Student studentRepository; + +// @Test +// public void whenAddingStudentsToCourse_thenCourseHasStudents() { +// // given +// Student student1 = new Student(); +// student1.setName("John"); +// Student student2 = new Student(); +// student2.setName("Jane"); +// studentRepository.saveAll(Arrays.asList(student1, student2)); + +// Course course = new Course(); +// course.setName("History"); +// courseRepository.save(course); + +// // when +// List students = studentRepository.findAll(); +// course.setStudents(students); +// courseRepository.save(course); + +// // then +// Course result = courseRepository.findById(course.getId()).get(); +// assertThat(result.getStudents()).containsExactlyInAnyOrder(student1, student2); +// } + +// } + +package com.baeldung.hibernate.associations; + + +import com.baeldung.associations.biredirectional.*; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; + +public class BidirectionalUnitTest { + + @Test + public void givenDepartmentWithEmployees_whenGetEmployees_thenReturnListWithEmployees() { + // given + Department department = new Department(); + Employee employee1 = new Employee(); + Employee employee2 = new Employee(); + department.getEmployees().add(employee1); + department.getEmployees().add(employee2); + + // when + List result = department.getEmployees(); + + // then + assertAll("department employees", + () -> assertEquals(2, result.size()), + () -> assertTrue(result.contains(employee1)), + () -> assertTrue(result.contains(employee2)) + ); + } + + @Test + public void givenCourseWithStudents_whenGetStudents_thenReturnListWithStudents() { + // given + Course course = new Course(); + Student student1 = new Student(); + Student student2 = new Student(); + course.getStudents().add(student1); + course.getStudents().add(student2); + + // when + List result = course.getStudents(); + + // then + assertAll("course students", + () -> assertEquals(2, result.size()), + () -> assertTrue(result.contains(student1)), + () -> assertTrue(result.contains(student2)) + ); + } + +} diff --git a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/DataJpaTest.java b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/DataJpaTest.java new file mode 100644 index 0000000000..184fae20c0 --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/DataJpaTest.java @@ -0,0 +1,5 @@ +package com.baeldung.hibernate.associations; + +public @interface DataJpaTest { + +} diff --git a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/UnidirectionalUnitTest.java b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/UnidirectionalUnitTest.java new file mode 100644 index 0000000000..790110a6d7 --- /dev/null +++ b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/UnidirectionalUnitTest.java @@ -0,0 +1,128 @@ + +// // import org.junit.jupiter.api.Assertions; +// // import org.junit.jupiter.api.Test; +// // import org.springframework.beans.factory.annotation.Autowired; +// // import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +// // import org.springframework.boot.test.context.SpringBootTest; +// // import org.springframework.transaction.annotation.Transactional; + +// // import java.util.Collections; +// // import java.util.List; + +// // @DataJpaTest +// // @Transactional +// // public class UnidirectionalUnitTest { + +// // @Autowired +// // private EntityManager entityManager; + +// // @Test +// // public void givenBookWithAuthor_whenSaved_thenFindBookByAuthor() { +// // // given +// // Author author = new Author(); +// // author.setName("John Doe"); + +// // Book book = new Book(); +// // book.setTitle("My Book"); +// // book.setAuthors(Collections.singleton(author)); + +// // entityManager.persist(author); +// // entityManager.persist(book); + +// // entityManager.flush(); +// // entityManager.clear(); + +// // // when +// // List booksByAuthor = entityManager.createQuery( +// // "select b from Book b join b.authors a where a.name = :name", Book.class) +// // .setParameter("name", "John Doe") +// // .getResultList(); + +// // // then +// // Assertions.assertEquals(1, booksByAuthor.size()); +// // Assertions.assertEquals(book, booksByAuthor.get(0)); +// // } +// // } + + +// package com.baeldung.hibernate.associations; + +// import com.baeldung.associations.unidirectional.*; + +// import org.junit.jupiter.api.Test; +// import org.springframework.beans.factory.annotation.Autowired; +// import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +// import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; + +// import java.util.List; +// import java.util.Set; + +// import static org.assertj.core.api.Assertions.assertThat; + +// @DataJpaTest +// public class UnidirectionalUnitTest { + +// @Autowired +// private TestEntityManager entityManager; + +// @Test +// public void givenDepartmentWithEmployees_whenFindById_thenDepartmentWithEmployeesReturned() { +// // given +// Employee employee1 = new Employee(); +// Employee employee2 = new Employee(); +// Department department = new Department(); +// department.setEmployees(List.of(employee1, employee2)); +// entityManager.persist(department); +// entityManager.flush(); + +// // when +// Department foundDepartment = entityManager.find(Department.class, department.getId()); + +// // then +// assertThat(foundDepartment).isEqualTo(department); +// assertThat(foundDepartment.getEmployees()).containsExactly(employee1, employee2); +// } + +// @Test +// public void givenEmployeeWithParkingSpot_whenFindById_thenEmployeeWithParkingSpotReturned() { +// // given +// ParkingSpot parkingSpot = new ParkingSpot(); +// entityManager.persist(parkingSpot); +// entityManager.flush(); +// Employee employee = new Employee(); +// employee.setParkingSpot(parkingSpot); +// entityManager.persist(employee); +// entityManager.flush(); + +// // when +// Employee foundEmployee = entityManager.find(Employee.class, employee.getId()); + +// // then +// assertThat(foundEmployee).isEqualTo(employee); +// assertThat(foundEmployee.getParkingSpot()).isEqualTo(parkingSpot); +// } + +// @Test +// public void givenBookWithAuthors_whenFindById_thenBookWithAuthorsReturned() { +// // given +// Author author1 = new Author(); +// Author author2 = new Author(); +// entityManager.persist(author1); +// entityManager.persist(author2); +// entityManager.flush(); +// Book book = new Book(); +// book.setAuthors(Set.of(author1, author2)); +// entityManager.persist(book); +// entityManager.flush(); + +// // when +// Book foundBook = entityManager.find(Book.class, book.getId()); + +// // then +// assertThat(foundBook).isEqualTo(book); +// assertThat(foundBook.getAuthors()).containsExactly(author1, author2); +// } + +// } + + From 1767ea3cdc4982644331c213abefc751d64bc20f Mon Sep 17 00:00:00 2001 From: Kingsley Amankwah Date: Thu, 27 Apr 2023 05:10:50 +0530 Subject: [PATCH 04/40] Hibernate Associations --- .../associations/BidirectionalUnitTest.java | 103 -------------- .../hibernate/associations/DataJpaTest.java | 5 - .../associations/UnidirectionalUnitTest.java | 128 ------------------ 3 files changed, 236 deletions(-) delete mode 100644 persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/BidirectionalUnitTest.java delete mode 100644 persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/DataJpaTest.java delete mode 100644 persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/UnidirectionalUnitTest.java diff --git a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/BidirectionalUnitTest.java b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/BidirectionalUnitTest.java deleted file mode 100644 index 5b7e01bff1..0000000000 --- a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/BidirectionalUnitTest.java +++ /dev/null @@ -1,103 +0,0 @@ -// package com.baeldung.hibernate.associations; - -// import org.junit.jupiter.api.Test; -// import org.junit.jupiter.api.extension.ExtendWith; -// import org.springframework.beans.factory.annotation.Autowired; -// import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -// import org.springframework.test.context.junit.jupiter.SpringExtension; - -// import java.util.Arrays; -// import java.util.List; -// import com.baeldung.associations.biredirectional.*; - - -// import static org.assertj.core.api.Assertions.assertThat; - -// @ExtendWith(SpringExtension.class) -// @DataJpaTest -// public class BidirectionalHibernateIntegrationTest { - -// @Autowired -// private Course courseRepository; - -// @Autowired -// private Student studentRepository; - -// @Test -// public void whenAddingStudentsToCourse_thenCourseHasStudents() { -// // given -// Student student1 = new Student(); -// student1.setName("John"); -// Student student2 = new Student(); -// student2.setName("Jane"); -// studentRepository.saveAll(Arrays.asList(student1, student2)); - -// Course course = new Course(); -// course.setName("History"); -// courseRepository.save(course); - -// // when -// List students = studentRepository.findAll(); -// course.setStudents(students); -// courseRepository.save(course); - -// // then -// Course result = courseRepository.findById(course.getId()).get(); -// assertThat(result.getStudents()).containsExactlyInAnyOrder(student1, student2); -// } - -// } - -package com.baeldung.hibernate.associations; - - -import com.baeldung.associations.biredirectional.*; - -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - -import java.util.List; - -public class BidirectionalUnitTest { - - @Test - public void givenDepartmentWithEmployees_whenGetEmployees_thenReturnListWithEmployees() { - // given - Department department = new Department(); - Employee employee1 = new Employee(); - Employee employee2 = new Employee(); - department.getEmployees().add(employee1); - department.getEmployees().add(employee2); - - // when - List result = department.getEmployees(); - - // then - assertAll("department employees", - () -> assertEquals(2, result.size()), - () -> assertTrue(result.contains(employee1)), - () -> assertTrue(result.contains(employee2)) - ); - } - - @Test - public void givenCourseWithStudents_whenGetStudents_thenReturnListWithStudents() { - // given - Course course = new Course(); - Student student1 = new Student(); - Student student2 = new Student(); - course.getStudents().add(student1); - course.getStudents().add(student2); - - // when - List result = course.getStudents(); - - // then - assertAll("course students", - () -> assertEquals(2, result.size()), - () -> assertTrue(result.contains(student1)), - () -> assertTrue(result.contains(student2)) - ); - } - -} diff --git a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/DataJpaTest.java b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/DataJpaTest.java deleted file mode 100644 index 184fae20c0..0000000000 --- a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/DataJpaTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.baeldung.hibernate.associations; - -public @interface DataJpaTest { - -} diff --git a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/UnidirectionalUnitTest.java b/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/UnidirectionalUnitTest.java deleted file mode 100644 index 790110a6d7..0000000000 --- a/persistence-modules/hibernate-mapping-2/src/test/java/com/baeldung/hibernate/associations/UnidirectionalUnitTest.java +++ /dev/null @@ -1,128 +0,0 @@ - -// // import org.junit.jupiter.api.Assertions; -// // import org.junit.jupiter.api.Test; -// // import org.springframework.beans.factory.annotation.Autowired; -// // import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -// // import org.springframework.boot.test.context.SpringBootTest; -// // import org.springframework.transaction.annotation.Transactional; - -// // import java.util.Collections; -// // import java.util.List; - -// // @DataJpaTest -// // @Transactional -// // public class UnidirectionalUnitTest { - -// // @Autowired -// // private EntityManager entityManager; - -// // @Test -// // public void givenBookWithAuthor_whenSaved_thenFindBookByAuthor() { -// // // given -// // Author author = new Author(); -// // author.setName("John Doe"); - -// // Book book = new Book(); -// // book.setTitle("My Book"); -// // book.setAuthors(Collections.singleton(author)); - -// // entityManager.persist(author); -// // entityManager.persist(book); - -// // entityManager.flush(); -// // entityManager.clear(); - -// // // when -// // List booksByAuthor = entityManager.createQuery( -// // "select b from Book b join b.authors a where a.name = :name", Book.class) -// // .setParameter("name", "John Doe") -// // .getResultList(); - -// // // then -// // Assertions.assertEquals(1, booksByAuthor.size()); -// // Assertions.assertEquals(book, booksByAuthor.get(0)); -// // } -// // } - - -// package com.baeldung.hibernate.associations; - -// import com.baeldung.associations.unidirectional.*; - -// import org.junit.jupiter.api.Test; -// import org.springframework.beans.factory.annotation.Autowired; -// import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -// import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; - -// import java.util.List; -// import java.util.Set; - -// import static org.assertj.core.api.Assertions.assertThat; - -// @DataJpaTest -// public class UnidirectionalUnitTest { - -// @Autowired -// private TestEntityManager entityManager; - -// @Test -// public void givenDepartmentWithEmployees_whenFindById_thenDepartmentWithEmployeesReturned() { -// // given -// Employee employee1 = new Employee(); -// Employee employee2 = new Employee(); -// Department department = new Department(); -// department.setEmployees(List.of(employee1, employee2)); -// entityManager.persist(department); -// entityManager.flush(); - -// // when -// Department foundDepartment = entityManager.find(Department.class, department.getId()); - -// // then -// assertThat(foundDepartment).isEqualTo(department); -// assertThat(foundDepartment.getEmployees()).containsExactly(employee1, employee2); -// } - -// @Test -// public void givenEmployeeWithParkingSpot_whenFindById_thenEmployeeWithParkingSpotReturned() { -// // given -// ParkingSpot parkingSpot = new ParkingSpot(); -// entityManager.persist(parkingSpot); -// entityManager.flush(); -// Employee employee = new Employee(); -// employee.setParkingSpot(parkingSpot); -// entityManager.persist(employee); -// entityManager.flush(); - -// // when -// Employee foundEmployee = entityManager.find(Employee.class, employee.getId()); - -// // then -// assertThat(foundEmployee).isEqualTo(employee); -// assertThat(foundEmployee.getParkingSpot()).isEqualTo(parkingSpot); -// } - -// @Test -// public void givenBookWithAuthors_whenFindById_thenBookWithAuthorsReturned() { -// // given -// Author author1 = new Author(); -// Author author2 = new Author(); -// entityManager.persist(author1); -// entityManager.persist(author2); -// entityManager.flush(); -// Book book = new Book(); -// book.setAuthors(Set.of(author1, author2)); -// entityManager.persist(book); -// entityManager.flush(); - -// // when -// Book foundBook = entityManager.find(Book.class, book.getId()); - -// // then -// assertThat(foundBook).isEqualTo(book); -// assertThat(foundBook.getAuthors()).containsExactly(author1, author2); -// } - -// } - - From d650f7ace7d112794c36f0a4c638bbe023158277 Mon Sep 17 00:00:00 2001 From: Kingsley Amankwah Date: Sun, 30 Apr 2023 15:53:49 +0530 Subject: [PATCH 05/40] getters and setters removed from code --- .../associations/biredirectional/Course.java | 22 +++++++++++++-- .../biredirectional/Employee.java | 25 ++++++++++++++++- .../associations/biredirectional/Student.java | 27 +++++++++++++++++-- .../associations/unidirectional/Author.java | 23 ++++++++++++++++ .../associations/unidirectional/Book.java | 24 +++++++++++++++++ 5 files changed, 116 insertions(+), 5 deletions(-) diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Course.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Course.java index aadc08c090..52d01c027c 100644 --- a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Course.java +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Course.java @@ -16,9 +16,27 @@ public class Course { inverseJoinColumns = @JoinColumn(name = "student_id")) private List students; - public List getStudents() { + public List getStudents() { return students; } - //getters and setters + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void setStudents(List students) { + this.students = students; + } } diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Employee.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Employee.java index 92514b9b8c..1e04379ae2 100644 --- a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Employee.java +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Employee.java @@ -15,5 +15,28 @@ public class Employee { @JoinColumn(name = "department_id") private Department department; - //getters and setters + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Department getDepartment() { + return department; + } + + public void setDepartment(Department department) { + this.department = department; + } } diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Student.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Student.java index a494f2475f..81e608f88e 100644 --- a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Student.java +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/biredirectional/Student.java @@ -14,7 +14,30 @@ public class Student { @ManyToMany(mappedBy = "students") private List courses; - - // getters and setters + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getCourses() { + return courses; + } + + public void setCourses(List courses) { + this.courses = courses; + } } diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Author.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Author.java index 6a106071a1..7e023683dc 100644 --- a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Author.java +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Author.java @@ -14,4 +14,27 @@ public class Author { @ManyToMany(fetch = FetchType.LAZY, mappedBy = "authors") private Set books; + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getBooks() { + return books; + } + + public void setBooks(Set books) { + this.books = books; + } } diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Book.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Book.java index 1467a819a0..25b192fb6b 100644 --- a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Book.java +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/associations/unidirectional/Book.java @@ -1,4 +1,5 @@ package com.baeldung.associations.unidirectional; + import jakarta.persistence.*; import java.util.Set; @@ -17,4 +18,27 @@ public class Book { inverseJoinColumns = @JoinColumn(name = "author_id")) private Set authors; + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Set getAuthors() { + return authors; + } + + public void setAuthors(Set authors) { + this.authors = authors; + } } From 4e7d1ffd1fbf8932746ee33d81510a2be3f33b4c Mon Sep 17 00:00:00 2001 From: Kingsley Amankwah Date: Sun, 30 Apr 2023 15:58:54 +0530 Subject: [PATCH 06/40] Comments removed --- .../src/main/java/com/baeldung/HibernateUtil.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/HibernateUtil.java b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/HibernateUtil.java index 8af6b12bae..26ad7e77ba 100644 --- a/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/HibernateUtil.java +++ b/persistence-modules/hibernate-mapping-2/src/main/java/com/baeldung/HibernateUtil.java @@ -7,7 +7,6 @@ import org.hibernate.service.ServiceRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -// import com.baeldung.associations.unidirectional.Department; import com.baeldung.manytomany.model.Employee; import com.baeldung.manytomany.model.Project; import com.baeldung.uuids.WebSiteUser; @@ -30,7 +29,6 @@ public class HibernateUtil { configuration.addAnnotatedClass(Element.class); configuration.addAnnotatedClass(Reservation.class); configuration.addAnnotatedClass(Sale.class); - // configuration.addAnnotatedClass(Department.class); configuration.configure("manytomany.cfg.xml"); LOGGER.debug("Hibernate Annotation Configuration loaded"); From 58d6a02c35e30a6997bbef39659d50443d5e2f21 Mon Sep 17 00:00:00 2001 From: technoddy Date: Sun, 14 May 2023 12:09:07 -0400 Subject: [PATCH 07/40] JPA Counting Row Implementation --- .../countrows/AccountStatsApplication.java | 11 ++ .../baeldung/countrows/entity/Account.java | 96 ++++++++++++ .../baeldung/countrows/entity/Permission.java | 39 +++++ .../repository/AccountRepository.java | 22 +++ .../repository/PermissionRepository.java | 12 ++ .../countrows/service/AccountStatsLogic.java | 123 +++++++++++++++ .../AccountStatsUnitTests.java | 147 ++++++++++++++++++ 7 files changed, 450 insertions(+) create mode 100644 persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/AccountStatsApplication.java create mode 100644 persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java create mode 100644 persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java create mode 100644 persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java create mode 100644 persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/PermissionRepository.java create mode 100644 persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java create mode 100644 persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/AccountStatsApplication.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/AccountStatsApplication.java new file mode 100644 index 0000000000..f5a99f0ad8 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/AccountStatsApplication.java @@ -0,0 +1,11 @@ +package com.baeldung.countrows; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AccountStatsApplication { + public static void main(String[] args) { + SpringApplication.run(AccountStatsApplication.class, args); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java new file mode 100644 index 0000000000..11e4cb412e --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java @@ -0,0 +1,96 @@ +package com.baeldung.countrows.entity; + +import javax.persistence.*; + +import java.security.PrivateKey; +import java.sql.Timestamp; +import java.time.Instant; +import java.util.Date; + +@Entity +@Table(name="ACCOUNTS") +public class Account { + @Id + @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "accounts_seq") + @SequenceGenerator(name = "accounts_seq", sequenceName = "accounts_seq", allocationSize = 1) + @Column(name = "user_id") + private int userId; + private String username; + private String password; + private String email; + private Timestamp createdOn; + private Timestamp lastLogin; + + @OneToOne + @JoinColumn(name = "permissions_id") + private Permission permission; + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + 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; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Timestamp getCreatedOn() { + return createdOn; + } + + public void setCreatedOn(Timestamp createdOn) { + this.createdOn = createdOn; + } + + public Timestamp getLastLogin() { + return lastLogin; + } + + public void setLastLogin(Timestamp lastLogin) { + this.lastLogin = lastLogin; + } + + public Permission getPermission() { + return permission; + } + + public void setPermission(Permission permission) { + this.permission = permission; + } + + @Override + public String toString() { + return "Account{" + + "userId=" + userId + + ", username='" + username + '\'' + + ", password='" + password + '\'' + + ", email='" + email + '\'' + + ", createdOn=" + createdOn + + ", lastLogin=" + lastLogin + + ", permission=" + permission + + '}'; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java new file mode 100644 index 0000000000..17e8ab9c12 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java @@ -0,0 +1,39 @@ +package com.baeldung.countrows.entity; + +import javax.persistence.*; + +@Entity +@Table(name="PERMISSIONS") +public class Permission { + + @Id + @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "permissions_id_sq") + @SequenceGenerator(name = "permissions_id_sq", sequenceName = "permissions_id_sq", allocationSize = 1) + private int id; + + private String type; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + @Override + public String toString() { + return "Permission{" + + "id=" + id + + ", type='" + type + '\'' + + '}'; + } +} diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java new file mode 100644 index 0000000000..875a2e7160 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java @@ -0,0 +1,22 @@ +package com.baeldung.countrows.repository; + +import com.baeldung.countrows.entity.Account; +import com.baeldung.countrows.entity.Permission; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.sql.Timestamp; +import java.util.Date; +import java.util.List; + +@Repository +public interface AccountRepository extends JpaRepository { + + long countByUsername(String username); + + long countByPermission(Permission permission); + + long countByPermissionAndCreatedOnGreaterThan(Permission permission, Timestamp ts); +} diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/PermissionRepository.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/PermissionRepository.java new file mode 100644 index 0000000000..5e598b52ef --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/PermissionRepository.java @@ -0,0 +1,12 @@ +package com.baeldung.countrows.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.baeldung.countrows.entity.Permission; + +@Repository +public interface PermissionRepository extends JpaRepository { + Permission findByType(String type); +} + diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java new file mode 100644 index 0000000000..f8f8d5905e --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java @@ -0,0 +1,123 @@ +package com.baeldung.countrows.service; + +import java.sql.Timestamp; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.persistence.criteria.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.baeldung.countrows.entity.Account; +import com.baeldung.countrows.entity.Permission; +import com.baeldung.countrows.repository.AccountRepository; +import com.baeldung.countrows.repository.PermissionRepository; + +@Service +public class AccountStatsLogic { + @Autowired + private AccountRepository accountRepository; + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private PermissionRepository permissionRepository; + + public long getAccountCount(){ + return accountRepository.count(); + } + + public long getAccountCountByUsername(String username){ + return accountRepository.countByUsername(username); + } + + public long getAccountCountByPermission(Permission permission){ + return accountRepository.countByPermission(permission); + } + + + public long getAccountCountByPermissionAndCreatedOn(Permission permission, Date date) throws ParseException { + return accountRepository.countByPermissionAndCreatedOnGreaterThan(permission, new Timestamp(date.getTime())); + } + + public long getAccountsUsingCQ() throws ParseException { + // creating criteria builder and query + CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = builder.createQuery(Long.class); + Root accountRoot = criteriaQuery.from(Account.class); + + // select query + criteriaQuery + .select(builder.count(accountRoot)); + + // execute and get the result + return entityManager.createQuery(criteriaQuery).getSingleResult(); + } + + public long getAccountsByPermissionUsingCQ(Permission permission) throws ParseException { + CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = builder.createQuery(Long.class); + Root accountRoot = criteriaQuery.from(Account.class); + + List predicateList = new ArrayList<>(); // list of predicates that will go in where clause + predicateList.add(builder.equal(accountRoot.get("permission"), permission)); + + criteriaQuery + .select(builder.count(accountRoot)) + .where(builder.and(predicateList.toArray(new Predicate[0]))); + + return entityManager.createQuery(criteriaQuery).getSingleResult(); + } + + public long getAccountsByPermissionAndCreateOnUsingCQ(Permission permission, Date date) throws ParseException { + // creating criteria builder and query + CriteriaBuilder builder = entityManager.getCriteriaBuilder(); // create builder + CriteriaQuery criteriaQuery = builder.createQuery(Long.class);// query instance + Root accountRoot = criteriaQuery.from(Account.class); // root instance + + // list of predicates that will go in where clause + List predicateList = new ArrayList<>(); + predicateList.add(builder.equal(accountRoot.get("permission"), permission)); + predicateList.add(builder.greaterThan(accountRoot.get("createdOn"), new Timestamp(date.getTime()))); + + // select query + criteriaQuery + .select(builder.count(accountRoot)) + .where(builder.and(predicateList.toArray(new Predicate[0]))); + + // execute and get the result + return entityManager.createQuery(criteriaQuery).getSingleResult(); + } + + public long getAccountsUsingJPQL() throws ParseException { + Query query = entityManager.createQuery("SELECT COUNT(*) FROM Account a"); + return (long) query.getSingleResult(); + } + + public long getAccountsByPermissionUsingJPQL(Permission permission) throws ParseException { + Query query = entityManager.createQuery("SELECT COUNT(*) FROM Account a WHERE a.permission = ?1"); + query.setParameter(1, permission); + return (long) query.getSingleResult(); + } + + public long getAccountsByPermissionAndCreatedOnUsingJPQL(Permission permission, Date date) throws ParseException { + Query query = entityManager.createQuery("SELECT COUNT(*) FROM Account a WHERE a.permission = ?1 and a.createdOn > ?2"); + query.setParameter(1, permission); + query.setParameter(2, new Timestamp(date.getTime())); + return (long) query.getSingleResult(); + } + + private static Date getDate() throws ParseException { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + Date parsedDate = dateFormat.parse("2023-04-29"); + + System.out.println("parseDate: "+parsedDate); + return parsedDate; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java new file mode 100644 index 0000000000..2be8e910d9 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java @@ -0,0 +1,147 @@ +package com.baeldung.boot.countrows.accountstatslogic; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import java.sql.Timestamp; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.util.Date; +import java.util.UUID; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.baeldung.countrows.AccountStatsApplication; +import com.baeldung.countrows.entity.Account; +import com.baeldung.countrows.entity.Permission; +import com.baeldung.countrows.repository.AccountRepository; +import com.baeldung.countrows.repository.PermissionRepository; +import com.baeldung.countrows.service.AccountStatsLogic; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +@SpringBootTest(classes = AccountStatsApplication.class) +class AccountStatsUnitTests { + + @Autowired + private PermissionRepository permissionRepository; + + @Autowired + private AccountRepository accountRepository; + + @Autowired + private AccountStatsLogic accountStatsLogic; + + @AfterEach + public void afterEach(){ + accountRepository.deleteAll(); + permissionRepository.deleteAll(); + } + + @Test + public void givenAccountInTable_whenPerformCount_returnsAppropriateCount(){ + savePermissions(); + Account account = saveAccount(); + assertThat(accountStatsLogic.getAccountCount()).isEqualTo(1); + } + + @Test + public void givenAccountInTable_whenPerformCountByUsernameOrPermission_returnsAppropriateCount() { + savePermissions(); + Account account = saveAccount(); + assertThat(accountStatsLogic.getAccountCountByUsername(account.getUsername())).isEqualTo(1); + assertThat(accountStatsLogic.getAccountCountByPermission(account.getPermission())).isEqualTo(1); + } + + @Test + public void givenAccountInTable_whenPerformCountByPermissionAndCreatedOn_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountCountByPermissionAndCreatedOn(account.getPermission(), account.getCreatedOn()); + assertThat(count).isEqualTo(1); + } + + @Test + public void givenAccountInTable_whenPerformCountUsingCQ_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountsUsingCQ(); + assertThat(count).isEqualTo(1); + } + + @Test + public void givenAccountInTable_whenPerformCountByPermissionUsingCQ_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountsByPermissionUsingCQ(account.getPermission()); + assertThat(count).isEqualTo(1); + } + + @Test + public void givenAccountInTable_whenPerformCountByPermissionAndCreatedOnUsingCQ_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountsByPermissionAndCreateOnUsingCQ(account.getPermission(), account.getCreatedOn()); + assertThat(count).isEqualTo(1); + } + + @Test + public void givenAccountInTable_whenPerformCountUsingJPQL_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountsUsingJPQL(); + assertThat(count).isEqualTo(1); + } + @Test + public void givenAccountInTable_whenPerformCountByPermissionUsingJPQL_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountsByPermissionUsingJPQL(account.getPermission()); + assertThat(count).isEqualTo(1); + } + @Test + public void givenAccountInTable_whenPerformCountByPermissionAndCreatedOnUsingJPQL_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountsByPermissionAndCreatedOnUsingJPQL(account.getPermission(), account.getCreatedOn()); + assertThat(count).isEqualTo(1); + } + + private Account saveAccount(){ + return accountRepository.save(getAccount()); + } + + private void savePermissions(){ + Permission editor = new Permission(); + editor.setType("editor"); + permissionRepository.save(editor); + + Permission admin = new Permission(); + admin.setType("admin"); + permissionRepository.save(admin); + } + + private static Date getDate() throws ParseException { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + Date parsedDate = dateFormat.parse("2023-04-29"); + return parsedDate; + } + + private Account getAccount() { + Permission permission = permissionRepository.findByType("admin"); + Account account = new Account(); + String seed = UUID.randomUUID().toString(); + account.setUsername("username_"+seed); + account.setEmail("username_"+seed+"@gmail.com"); + account.setPermission(permission); + account.setPassword("password_q1234"); + account.setCreatedOn(Timestamp.from(Instant.now())); + account.setLastLogin(Timestamp.from(Instant.now())); + return account; + } +} From ebbd80e6c7928fd05416e321c4870a265ab228fc Mon Sep 17 00:00:00 2001 From: technoddy Date: Sun, 14 May 2023 12:38:41 -0400 Subject: [PATCH 08/40] updating class name for tests to abide by policy --- ...{AccountStatsUnitTests.java => AccountStatsUnitTest.java} | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) rename persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/{AccountStatsUnitTests.java => AccountStatsUnitTest.java} (96%) diff --git a/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java similarity index 96% rename from persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java rename to persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java index 2be8e910d9..98269547c3 100644 --- a/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java +++ b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java @@ -10,8 +10,6 @@ import java.util.Date; import java.util.UUID; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.baeldung.countrows.AccountStatsApplication; @@ -23,10 +21,9 @@ import com.baeldung.countrows.service.AccountStatsLogic; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; @SpringBootTest(classes = AccountStatsApplication.class) -class AccountStatsUnitTests { +class AccountStatsUnitTest { @Autowired private PermissionRepository permissionRepository; From 01e8fa41fddeabd892f7c52f46044d7a3bebda54 Mon Sep 17 00:00:00 2001 From: technoddy Date: Thu, 25 May 2023 23:40:16 -0400 Subject: [PATCH 09/40] Addressing PR feedback --- .../baeldung/countrows/entity/Account.java | 34 ++---------------- .../baeldung/countrows/entity/Permission.java | 21 ++--------- .../repository/AccountRepository.java | 1 + .../countrows/service/AccountStatsLogic.java | 35 ++++++++----------- .../AccountStatsUnitTest.java | 29 +++++++-------- 5 files changed, 34 insertions(+), 86 deletions(-) diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java index 11e4cb412e..d422c30a0e 100644 --- a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java @@ -8,10 +8,10 @@ import java.time.Instant; import java.util.Date; @Entity -@Table(name="ACCOUNTS") +@Table(name = "ACCOUNTS") public class Account { @Id - @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "accounts_seq") + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "accounts_seq") @SequenceGenerator(name = "accounts_seq", sequenceName = "accounts_seq", allocationSize = 1) @Column(name = "user_id") private int userId; @@ -25,14 +25,6 @@ public class Account { @JoinColumn(name = "permissions_id") private Permission permission; - public int getUserId() { - return userId; - } - - public void setUserId(int userId) { - this.userId = userId; - } - public String getUsername() { return username; } @@ -41,18 +33,10 @@ public class Account { this.username = username; } - public String getPassword() { - return password; - } - public void setPassword(String password) { this.password = password; } - public String getEmail() { - return email; - } - public void setEmail(String email) { this.email = email; } @@ -65,10 +49,6 @@ public class Account { this.createdOn = createdOn; } - public Timestamp getLastLogin() { - return lastLogin; - } - public void setLastLogin(Timestamp lastLogin) { this.lastLogin = lastLogin; } @@ -83,14 +63,6 @@ public class Account { @Override public String toString() { - return "Account{" + - "userId=" + userId + - ", username='" + username + '\'' + - ", password='" + password + '\'' + - ", email='" + email + '\'' + - ", createdOn=" + createdOn + - ", lastLogin=" + lastLogin + - ", permission=" + permission + - '}'; + return "Account{" + "userId=" + userId + ", username='" + username + '\'' + ", password='" + password + '\'' + ", email='" + email + '\'' + ", createdOn=" + createdOn + ", lastLogin=" + lastLogin + ", permission=" + permission + '}'; } } \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java index 17e8ab9c12..9acedf0558 100644 --- a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java @@ -3,37 +3,22 @@ package com.baeldung.countrows.entity; import javax.persistence.*; @Entity -@Table(name="PERMISSIONS") +@Table(name = "PERMISSIONS") public class Permission { @Id - @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "permissions_id_sq") + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "permissions_id_sq") @SequenceGenerator(name = "permissions_id_sq", sequenceName = "permissions_id_sq", allocationSize = 1) private int id; private String type; - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getType() { - return type; - } - public void setType(String type) { this.type = type; } @Override public String toString() { - return "Permission{" + - "id=" + id + - ", type='" + type + '\'' + - '}'; + return "Permission{" + "id=" + id + ", type='" + type + '\'' + '}'; } } diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java index 875a2e7160..422962ce45 100644 --- a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java @@ -2,6 +2,7 @@ package com.baeldung.countrows.repository; import com.baeldung.countrows.entity.Account; import com.baeldung.countrows.entity.Permission; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java index f8f8d5905e..e4e716b4ce 100644 --- a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java @@ -11,8 +11,10 @@ import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import javax.persistence.criteria.*; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; + import com.baeldung.countrows.entity.Account; import com.baeldung.countrows.entity.Permission; import com.baeldung.countrows.repository.AccountRepository; @@ -29,19 +31,18 @@ public class AccountStatsLogic { @Autowired private PermissionRepository permissionRepository; - public long getAccountCount(){ + public long getAccountCount() { return accountRepository.count(); } - public long getAccountCountByUsername(String username){ + public long getAccountCountByUsername(String username) { return accountRepository.countByUsername(username); } - public long getAccountCountByPermission(Permission permission){ + public long getAccountCountByPermission(Permission permission) { return accountRepository.countByPermission(permission); } - public long getAccountCountByPermissionAndCreatedOn(Permission permission, Date date) throws ParseException { return accountRepository.countByPermissionAndCreatedOnGreaterThan(permission, new Timestamp(date.getTime())); } @@ -53,11 +54,11 @@ public class AccountStatsLogic { Root accountRoot = criteriaQuery.from(Account.class); // select query - criteriaQuery - .select(builder.count(accountRoot)); + criteriaQuery.select(builder.count(accountRoot)); // execute and get the result - return entityManager.createQuery(criteriaQuery).getSingleResult(); + return entityManager.createQuery(criteriaQuery) + .getSingleResult(); } public long getAccountsByPermissionUsingCQ(Permission permission) throws ParseException { @@ -68,11 +69,11 @@ public class AccountStatsLogic { List predicateList = new ArrayList<>(); // list of predicates that will go in where clause predicateList.add(builder.equal(accountRoot.get("permission"), permission)); - criteriaQuery - .select(builder.count(accountRoot)) + criteriaQuery.select(builder.count(accountRoot)) .where(builder.and(predicateList.toArray(new Predicate[0]))); - return entityManager.createQuery(criteriaQuery).getSingleResult(); + return entityManager.createQuery(criteriaQuery) + .getSingleResult(); } public long getAccountsByPermissionAndCreateOnUsingCQ(Permission permission, Date date) throws ParseException { @@ -87,12 +88,12 @@ public class AccountStatsLogic { predicateList.add(builder.greaterThan(accountRoot.get("createdOn"), new Timestamp(date.getTime()))); // select query - criteriaQuery - .select(builder.count(accountRoot)) + criteriaQuery.select(builder.count(accountRoot)) .where(builder.and(predicateList.toArray(new Predicate[0]))); // execute and get the result - return entityManager.createQuery(criteriaQuery).getSingleResult(); + return entityManager.createQuery(criteriaQuery) + .getSingleResult(); } public long getAccountsUsingJPQL() throws ParseException { @@ -112,12 +113,4 @@ public class AccountStatsLogic { query.setParameter(2, new Timestamp(date.getTime())); return (long) query.getSingleResult(); } - - private static Date getDate() throws ParseException { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - Date parsedDate = dateFormat.parse("2023-04-29"); - - System.out.println("parseDate: "+parsedDate); - return parsedDate; - } } \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java index 98269547c3..af825601aa 100644 --- a/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java +++ b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java @@ -35,15 +35,15 @@ class AccountStatsUnitTest { private AccountStatsLogic accountStatsLogic; @AfterEach - public void afterEach(){ + public void afterEach() { accountRepository.deleteAll(); permissionRepository.deleteAll(); } @Test - public void givenAccountInTable_whenPerformCount_returnsAppropriateCount(){ + public void givenAccountInTable_whenPerformCount_returnsAppropriateCount() { savePermissions(); - Account account = saveAccount(); + saveAccount(); assertThat(accountStatsLogic.getAccountCount()).isEqualTo(1); } @@ -66,7 +66,7 @@ class AccountStatsUnitTest { @Test public void givenAccountInTable_whenPerformCountUsingCQ_returnsAppropriateCount() throws ParseException { savePermissions(); - Account account = saveAccount(); + saveAccount(); long count = accountStatsLogic.getAccountsUsingCQ(); assertThat(count).isEqualTo(1); } @@ -90,10 +90,11 @@ class AccountStatsUnitTest { @Test public void givenAccountInTable_whenPerformCountUsingJPQL_returnsAppropriateCount() throws ParseException { savePermissions(); - Account account = saveAccount(); + saveAccount(); long count = accountStatsLogic.getAccountsUsingJPQL(); assertThat(count).isEqualTo(1); } + @Test public void givenAccountInTable_whenPerformCountByPermissionUsingJPQL_returnsAppropriateCount() throws ParseException { savePermissions(); @@ -101,6 +102,7 @@ class AccountStatsUnitTest { long count = accountStatsLogic.getAccountsByPermissionUsingJPQL(account.getPermission()); assertThat(count).isEqualTo(1); } + @Test public void givenAccountInTable_whenPerformCountByPermissionAndCreatedOnUsingJPQL_returnsAppropriateCount() throws ParseException { savePermissions(); @@ -109,11 +111,11 @@ class AccountStatsUnitTest { assertThat(count).isEqualTo(1); } - private Account saveAccount(){ + private Account saveAccount() { return accountRepository.save(getAccount()); } - private void savePermissions(){ + private void savePermissions() { Permission editor = new Permission(); editor.setType("editor"); permissionRepository.save(editor); @@ -123,18 +125,13 @@ class AccountStatsUnitTest { permissionRepository.save(admin); } - private static Date getDate() throws ParseException { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - Date parsedDate = dateFormat.parse("2023-04-29"); - return parsedDate; - } - private Account getAccount() { Permission permission = permissionRepository.findByType("admin"); Account account = new Account(); - String seed = UUID.randomUUID().toString(); - account.setUsername("username_"+seed); - account.setEmail("username_"+seed+"@gmail.com"); + String seed = UUID.randomUUID() + .toString(); + account.setUsername("username_" + seed); + account.setEmail("username_" + seed + "@gmail.com"); account.setPermission(permission); account.setPassword("password_q1234"); account.setCreatedOn(Timestamp.from(Instant.now())); From 4487183c83b17b6ad757f416190d7991bf8df57e Mon Sep 17 00:00:00 2001 From: "thibault.faure" Date: Mon, 22 May 2023 23:49:35 +0200 Subject: [PATCH 10/40] BAEL-5773 Code for the Replacing Variables in a Document Template with Java article --- apache-poi-2/pom.xml | 13 ++-- .../poi/replacevariables/DocTextReplacer.java | 38 ++++++++++ .../DocxNaiveTextReplacer.java | 63 +++++++++++++++++ .../replacevariables/DocxTextReplacer.java | 65 ++++++++++++++++++ .../src/main/resources/baeldung-copy.docx | Bin 0 -> 15602 bytes apache-poi-2/src/main/resources/baeldung.doc | Bin 0 -> 28672 bytes apache-poi-2/src/main/resources/baeldung.docx | Bin 0 -> 15598 bytes .../DocTextReplacerUnitTest.java | 31 +++++++++ .../DocxNaiveTextReplacerUnitTest.java | 31 +++++++++ .../DocxTestReplacerUnitTest.java | 31 +++++++++ 10 files changed, 268 insertions(+), 4 deletions(-) create mode 100644 apache-poi-2/src/main/java/com/baeldung/poi/replacevariables/DocTextReplacer.java create mode 100644 apache-poi-2/src/main/java/com/baeldung/poi/replacevariables/DocxNaiveTextReplacer.java create mode 100644 apache-poi-2/src/main/java/com/baeldung/poi/replacevariables/DocxTextReplacer.java create mode 100644 apache-poi-2/src/main/resources/baeldung-copy.docx create mode 100644 apache-poi-2/src/main/resources/baeldung.doc create mode 100644 apache-poi-2/src/main/resources/baeldung.docx create mode 100644 apache-poi-2/src/test/java/com/baeldung/poi/replacevariables/DocTextReplacerUnitTest.java create mode 100644 apache-poi-2/src/test/java/com/baeldung/poi/replacevariables/DocxNaiveTextReplacerUnitTest.java create mode 100644 apache-poi-2/src/test/java/com/baeldung/poi/replacevariables/DocxTestReplacerUnitTest.java diff --git a/apache-poi-2/pom.xml b/apache-poi-2/pom.xml index af959292fa..9a01a76d73 100644 --- a/apache-poi-2/pom.xml +++ b/apache-poi-2/pom.xml @@ -1,7 +1,7 @@ - + 4.0.0 apache-poi-2 0.0.1-SNAPSHOT @@ -19,10 +19,15 @@ poi-ooxml ${poi.version} + + org.apache.poi + poi-scratchpad + ${poi.version} + - 5.2.0 + 5.2.3 \ No newline at end of file diff --git a/apache-poi-2/src/main/java/com/baeldung/poi/replacevariables/DocTextReplacer.java b/apache-poi-2/src/main/java/com/baeldung/poi/replacevariables/DocTextReplacer.java new file mode 100644 index 0000000000..f661551ce9 --- /dev/null +++ b/apache-poi-2/src/main/java/com/baeldung/poi/replacevariables/DocTextReplacer.java @@ -0,0 +1,38 @@ +package com.baeldung.poi.replacevariables; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.hwpf.usermodel.Range; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; + +public class DocTextReplacer { + + public void replaceText() throws IOException { + String filePath = getClass().getClassLoader() + .getResource("baeldung.doc") + .getPath(); + try (InputStream inputStream = new FileInputStream(filePath); POIFSFileSystem fileSystem = new POIFSFileSystem(inputStream)) { + HWPFDocument doc = new HWPFDocument(fileSystem); + doc = replaceText(doc, "Baeldung", "Hello"); + saveFile(filePath, doc); + doc.close(); + } + } + + private HWPFDocument replaceText(HWPFDocument doc, String originalText, String updatedText) { + Range range = doc.getRange(); + range.replaceText(originalText, updatedText); + return doc; + } + + private void saveFile(String filePath, HWPFDocument doc) throws IOException { + try (FileOutputStream out = new FileOutputStream(filePath)) { + doc.write(out); + } + } + +} diff --git a/apache-poi-2/src/main/java/com/baeldung/poi/replacevariables/DocxNaiveTextReplacer.java b/apache-poi-2/src/main/java/com/baeldung/poi/replacevariables/DocxNaiveTextReplacer.java new file mode 100644 index 0000000000..34c2bc43e5 --- /dev/null +++ b/apache-poi-2/src/main/java/com/baeldung/poi/replacevariables/DocxNaiveTextReplacer.java @@ -0,0 +1,63 @@ +package com.baeldung.poi.replacevariables; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFParagraph; +import org.apache.poi.xwpf.usermodel.XWPFRun; +import org.apache.poi.xwpf.usermodel.XWPFTable; +import org.apache.poi.xwpf.usermodel.XWPFTableCell; +import org.apache.poi.xwpf.usermodel.XWPFTableRow; + +public class DocxNaiveTextReplacer { + + public void replaceText() throws IOException { + String filePath = getClass().getClassLoader() + .getResource("baeldung-copy.docx") + .getPath(); + try (InputStream inputStream = new FileInputStream(filePath)) { + XWPFDocument doc = new XWPFDocument(inputStream); + doc = replaceText(doc, "Baeldung", "Hello"); + saveFile(filePath, doc); + doc.close(); + } + } + + private XWPFDocument replaceText(XWPFDocument doc, String originalText, String updatedText) { + replaceTextInParagraphs(doc.getParagraphs(), originalText, updatedText); + for (XWPFTable tbl : doc.getTables()) { + for (XWPFTableRow row : tbl.getRows()) { + for (XWPFTableCell cell : row.getTableCells()) { + replaceTextInParagraphs(cell.getParagraphs(), originalText, updatedText); + } + } + } + return doc; + } + + private void replaceTextInParagraphs(List paragraphs, String originalText, String updatedText) { + paragraphs.forEach(paragraph -> replaceTextInParagraph(paragraph, originalText, updatedText)); + } + + private void replaceTextInParagraph(XWPFParagraph paragraph, String originalText, String updatedText) { + List runs = paragraph.getRuns(); + for (XWPFRun run : runs) { + String text = run.getText(0); + if (text != null && text.contains(originalText)) { + String updatedRunText = text.replace(originalText, updatedText); + run.setText(updatedRunText, 0); + } + } + } + + private void saveFile(String filePath, XWPFDocument doc) throws IOException { + try (FileOutputStream out = new FileOutputStream(filePath)) { + doc.write(out); + } + } + +} diff --git a/apache-poi-2/src/main/java/com/baeldung/poi/replacevariables/DocxTextReplacer.java b/apache-poi-2/src/main/java/com/baeldung/poi/replacevariables/DocxTextReplacer.java new file mode 100644 index 0000000000..2d08d24a4e --- /dev/null +++ b/apache-poi-2/src/main/java/com/baeldung/poi/replacevariables/DocxTextReplacer.java @@ -0,0 +1,65 @@ +package com.baeldung.poi.replacevariables; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Objects; + +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFParagraph; +import org.apache.poi.xwpf.usermodel.XWPFRun; +import org.apache.poi.xwpf.usermodel.XWPFTable; +import org.apache.poi.xwpf.usermodel.XWPFTableCell; +import org.apache.poi.xwpf.usermodel.XWPFTableRow; + +public class DocxTextReplacer { + + public void replaceText() throws IOException { + String filePath = getClass().getClassLoader() + .getResource("baeldung.docx") + .getPath(); + try (InputStream inputStream = new FileInputStream(filePath)) { + XWPFDocument doc = new XWPFDocument(inputStream); + doc = replaceText(doc, "Baeldung", "Hello"); + saveFile(filePath, doc); + doc.close(); + } + } + + private XWPFDocument replaceText(XWPFDocument doc, String originalText, String updatedText) { + replaceTextInParagraphs(doc.getParagraphs(), originalText, updatedText); + for (XWPFTable tbl : doc.getTables()) { + for (XWPFTableRow row : tbl.getRows()) { + for (XWPFTableCell cell : row.getTableCells()) { + replaceTextInParagraphs(cell.getParagraphs(), originalText, updatedText); + } + } + } + return doc; + } + + private void replaceTextInParagraphs(List paragraphs, String originalText, String updatedText) { + paragraphs.forEach(paragraph -> replaceTextInParagraph(paragraph, originalText, updatedText)); + } + + private void replaceTextInParagraph(XWPFParagraph paragraph, String originalText, String updatedText) { + String paragraphText = paragraph.getParagraphText(); + if (paragraphText.contains(originalText)) { + String updatedParagraphText = paragraphText.replace(originalText, updatedText); + while (paragraph.getRuns().size() > 0) { + paragraph.removeRun(0); + } + XWPFRun newRun = paragraph.createRun(); + newRun.setText(updatedParagraphText); + } + } + + private void saveFile(String filePath, XWPFDocument doc) throws IOException { + try (FileOutputStream out = new FileOutputStream(filePath)) { + doc.write(out); + } + } + +} diff --git a/apache-poi-2/src/main/resources/baeldung-copy.docx b/apache-poi-2/src/main/resources/baeldung-copy.docx new file mode 100644 index 0000000000000000000000000000000000000000..2cb76e8ffd0cf583f7d174821989c0e520f189f6 GIT binary patch literal 15602 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 literal 0 HcmV?d00001 diff --git a/apache-poi-2/src/main/resources/baeldung.doc b/apache-poi-2/src/main/resources/baeldung.doc new file mode 100644 index 0000000000000000000000000000000000000000..1b8474d65ba18a9e71ceba5bfe51eacf820e3ab6 GIT binary patch literal 28672 zcmeHQ2V7Lg)}P&F7etVyN>Nx4l_)N~h@vzVDFTYv#RZn;Qe2AI0xC941ngamBDNr+ z*hK{!mWT~CieimMR5U0W%YNrvxUg(QN%G$N<$Z5Q|M$$CnK@_fnYs5)Wy>$9SFPWv zf0xL(K7>U+N!k#O6rTZp8#>G-#18z(`y`P_kZlbBuiX6?S)e-i80kmaC=gPkaRe)o z5U5#jN`%Y+v?C$WA<k*IyuPbb(*dB(M= z44e_xaLSLL@<23j6%C%V0nJ-wZ_ zXWzgVBjsrRGq8&jaOivu(PSprK??$pfm#B^_J@v6R}JmpOX2$1zkj9m(30r-!g7oT zCT(Y$(&eMWG^O*mMCo+0lx~kSZ7Dy^r}fj}mZ+>AI!xP{4!1;UxpY0s(yztKrvF!k z>H2D^+%56x^8Q)cl01Aj4~G}&K6ptvL91sI4Y=YLMehFj7H|^?MPW&?5sH3^kwP(V zVw^ZEK~d37z-x?9RBWqC2Y4aE@HnxMmmmyHjEalpg@}cM@hWtzs%vZo7o)Vx9KntJ^&;b|#Isyy< z#sCvQCx9uSGoTBA4{!%~0DJ(xfU$sJKnx%OkO)WuBm*V_QUH?xlL1ozQvuTe-vUwr zX@Kbf?0Y`Dbrsy%;@xm9*uHMzx{QL^1*x-B;zgwKKS}v~HE?tyulhpwNsSea3F<>b zl^818kXgNkY3+0EtN7MaAguOTJ4K=PsBEqQ0Tagf!DMMh& zhzMI7e4>7`f@&|{L1uY-f%c+|?_v5KEc^a_Ep6`KqysI-G)wkeI*;7{AGbi$lYlR* z&pj&~b7GYh$uKG?x8N02IU5(`uuTA+vU1p_fX)T*N+~F3>H<`<%9(bgjU|=ADIULS ztm36r&3V93!S8Zcj+!cZfMM1lGT zQ>eHsK$Zj6eg*chLF{WthTSY*LrXIHK;D+({vG_yaKE%%9VtJ}lcoDwkw!L8B+SNn z0%ZCBi{bc&`n8631dCSWBrI`M03HEwxq}1y2y_5l0QP|XfFM9PAQ>Du~IUo&C1*ieQR#L(R@Bo$o z7l1tOKWCTEy;pdk-p@;c_yYm}!JZ6-7|%8ev48|XA^?(*L4=HZDPaOt;bIsa2SRZ~ zOk#+Dh#(A`e_$1k#lTg^9N0_g?xjP#J(-kD0r*j_v`m!I7x#J#cv>o~hid1OuS#Q6vmv9f(tq8u<&W$sk)zYQ>X~KEw#V-b_XxqN1cuaQ)Mg z!y%q<#{$qK1dX^T%$3TceNu@qJvFjS8Te@O$tSfRh&qE0lDQ4}+cwM3Bko{rv_85% zU`Ylsq4a4s>cg6dgFC17X?#VW6{Sz3QJ-}F=KA7Ekqg`(>?l>?Y7<<=tzxK>fmFQ< z;hI3zZ2+{Bdi{iShuxH#8zUK7fI%mfJjBOg4}dc9Z}N^wAIBOCfQ4bOCTy>8>qcOQ zMSLWtg_`|j@k$cF@BxcxHE7iMf=21`{!yC0Hw#wbI8=Yim^`_yb_AF1JAmmmfsS&I zi%k^9CI$yiiWeq~;itriwr8ImRBFlXSLgX*=EELds|#I}IzO3lYQd==rXD@L!c?d1 zdSTws_jNv(0^K(AbVTMiZ0gqbx-UL#q*zqCe084Jj#qBoO`jSJ7?XR)!SBY8LGz~T z>-HApsx7ZQP<+VDVNTk>c`FC!PI(j`;Zx|mAWLkNweiyLj?A-m$z9SurnNht6mU!T z>AY;m`(^Ie9XI_Xd zwN#n&V%FiA7pDbWD%I_rY>}JgZn0q+xoeghX<~5G;OR}jQyk@kO6eP4)NOJ8lt2I7 z-NnD~bXIQVl-_gidp7cJvh$JD8D+CJ=5j9${^QskL3~# zwYfL^4h_zC3%gjxz2w#JrfrC6YF_q);A=+9*XmW-`&@plGx(arxctn`Ws+T`mgm;` z9ZTI|{;;1ytixiTs0ShIH(T5vayV&oub;BX_pjp3=!n64Y-w^lJ`mU#PF0H$H z?cx2I4nN(|y1L3+b%gn9Mb!-9dH&qJHB-&=3^xDl+2Mq_=G=7=mpCnWT?PHD zT}IGX`&{9zu-MfjyyFZUxW(-srw*?^yff^nxgL7O))|QjQul==D%ZcjbCz)1NIlieLb4EukTfF)0bS)+2QEBUQi}k);y<*LZ zHHQ=GqI?c(o?{CJmRj8D_Ret7Y;)eg>orEN53Z|x<7^zD!8@aIt0r&w+lhPoetgjG z=Y{GEb}GJ_cim03??UU!k)t%-hxfmy<2`|S~wF#e0GO5Gj1=>|8bdDQIT%; z@j4BynLn3aoU5|)+OTdPpY4CuZq`{31*P8eZ)JaD&J-5_qv+XBC% zgWkX0QtOPXd-O2L`3K?5V<}@^l$E*`N97Lw@k+Az zqrS^S>--@vt~eEqUdPF~%N?|G!p@|MYonIvRS;ot#{)NCzv+LY#Nc;_rH(HGubwIy z@4x9tVfu^YQRDix-QlWNd?0;?y~C=QQAaq!w?AtXkNr7n*sn{!Rn0IPc+&gv;G#Vj zSFW?4^PO&GQi;R1C9%_{Z93%QYWv_~?jGHp9{CwXx*ct9v(uP^O$Xj9i^>=fsT6R_ zZLx~u%Qv37u2s2a0_IZhr@66FtWVqg`lVhr>^DkR?@~s4OLcGWjLfdHS8pu5dq?rd zVn)x@-yT)pc)Ba%$U5iLZ{Jj3yK#HulFobQFDzd?rS7tWIzQgxp60*~ z`bHi**|#FTv)7wA^6vDX&srv=E=+%Z{@wB8&K{4C7fo#2dFirVi?qb%6Sj!@UH@T{ zM}SGdTupQ5*9Hcm)sB^#ZsrG{FEWmp@%_fS^b}u@)m@$}ny&3TtDHaYn8lFxt~Gmw zt3I9@yC~q=mYZ*n_b)j-ee=wzMnleiS6A-w!}Z+4%#djPscL1X`xQDobl1G5uF<<= z$eBZf(q_e%br3u5xLd236@DxBPTu9~{lx=M^4Cn6Yo&Q3{C-gSy(_bxWt&>>TsPk; z-R#wZ<%!4YR!p0-d3+7aE9k&`t7A(KTKvSxmoIwJP`0OiPR%f~E-d=~?PU&N| zgwHt@lu>#2xL(Ke10!d>F+8cY<_8k`;^HsuIKE3q+FN+u$>eRT4jDGCazOI-txpx& zK3)=-uxoYKy14~zd*-?g*b-?X$@2p}%aOg)1j`1V`iGH@}U&S*u=T zZ^qn|nR7NicNBN$t>C$v?`=KNWzhcYX_s|k)1IG>o*c4p^mRs$+CEn$`E}FV-TyFW z*@E{~rM10cPXrYn2+7;kZACS|)?r)x{4u`sU#3m{;OlGPyRef=QdrN>%350o=kFy) zUPJ{|UT|1*ZtJ)AH!XU(zI5M{u<+6)YM0Bj&bO_#i>}I6om_jp>)4*J_0+wlh`nB} zEuU$`xM1VjUT4YbwJGqkpwb%@f-w0XzQ4zO_h#%Io%;=vjjD}MD) z`9{;y_R`rwmCAlyU-oHRD2UjN3JyP4fqtRMe6ByHKYYa(~&$Tgb& zg~N;mqVPr6T5bavFXs=+|HJM}{!2h<6-i?N!WtqIzT` zL!CQgQU}{#roS5U=-2%di){LC%p0b6IfFzN{G#rkGI_{^F_U^H9WcMbzZ*3_T|L&m zO^jY;)jTD`nGqMa1X;M>-&%aze0221A)CtIyGCl;{<`CIr~rCa?!LIQhvNw z%-f>xyQQDw=BlPDxQD*g&*S!Tb51bUFIly0{ev5-scX(H6dT|4^jL8$=~7vttB>g; z!_E^*hn>1m>7u#D-FELQC)4!IrMJ3lT$1^H2gk}}Ys2qr{8z?01TD_p<$bzlM1K6I zttWP<1uYaYpFi(+Y>PvV<|nS}+@Vi}!lP+QDHHvF+OEe<(OcTJ(BzYj@@4a9E8{jK zstBLX-K4&9sFux&i1;;U5}bbTws-mjyIwZBS1il6bKAKM9p}4Y z7WV8ErDJ#bOt-Dk2X-wlDm|oPe*M+tez(WjIaocg-Bl8?Ws23q*q;(A-PUCdYh#%b z+jqd#!yc}do3&SsxT1Ccq3w3@8`0JLj=!qNhWd8$1Qe6)Zs-XA~c zsu#1??SU8r_}q7u`6kx)VyKV1)Mve+SL3T(VyTs0H)EnwT-@aY-0UuubIX6c!b*Q& zr)uBVG@$yKYQDJ=e~zGdMbyD%Ysxf3t#4aJZq-+Eda`7~%40G6su#En))_SKMz64f zaWfXgIXu&j$o4k#?P5CEjBmAE+^(zFqSfUYf$!4t9XDhKJuum@$@TQXa?iS?X*n-f zF{Yj{JsiTFa+T;U^XGR@3aQsf= ztuvTCptIakHy4sgxzBWZ{k@wDknQ(1<+cQSO7#L|Gs^a(nlkD^2UDs)Ro}OgGQX@O z*-lN9q>9f;qPjS;GGrS;lZ;L_utrKol1%bT*kJOfc!&M^(AEz$sKD z_7%kQKtODQlfc;|GBGjU$-*Kb6gr)P1b$q+Fc#wApht`#5rX0fi!iZZA_$HVSy)?I z+FQg3qGC;WArV&2CZa?u6JBBp_`=46FC@YmdDh4SU)Xr?2|`0*hyy7aJTwR5>p6{S zY-o-RoyL~t*wP$3nqx}ig@2`^F<6+0g82#EhLtL8e!Hf zga|HCssVlV!a%SZVb$Pvb~U0 zp+45xkQ|8XM#=*1sR@k@;(^54(3{|Ck;Uv$1ka)1{(GDf!ZRUwu%vFpHfm~t+NKV2 z=sQHYXc>u%N*Zk;+`xnjegXcsr28By2W=$x!4l*(e$vU3m1T;bjO^ZVb%V!BGVW+3+dtZ8-`|bS-Lk zrDoOYXCeo*%VO-5x=ogpA2k@`1)OWcj26xxMtvsiP_J8!jfz>6?gvv$Nr~*8yTiPg z2qc71Wgx_zZ;lpIWBsXo^|Of)P$p~!uJu+|V1v~;sGCEoB&GzPIBaob9cVy@y3txV zrzil6`@%I5WWZT1cnGYN(sW4;&cx$t6Cw8=7AYdoPl=(LbSQ-C8I7cB4z-ucQ6Zv^RNSR+-l z*1dY?7s=h0twg$a-E{*S?^KAuk0Hiq0kHKg2Vie$BLJI20RVeCrvcawt^n}GQw6{m zaxDPgq$(f;>s%Koc4~2r5qmWrKyksvA1L%I$Y`M0iwXnE1u6oHv*(FGQ9rg|?0C>k zQPz)n0wbeB1WBSqUVlN7Sor1iScXB^`xWuS;u2#h*8Esg(iT+O_C{_1MJ0e8_d82_8U%l7~tTZV`8osWT! zV`dz?;`}3y)#Cv;2Y}P`I0ujpz%lK20Qe&{WHA6|fK~%=Y`qbHWBTm?+(Wb*fO7zc z04Tc*@VT+R^q83*JL8NR@=-E9%hVDz1m&0yL2YqGB{-PJLI*}AiiDIXDjH|8>g5u` z13xld0GP!SfMN7&0S1T#F);$MXp%=+4R(>-`BXqD17g!5ydI%jYLwnfT zJ390bgoRu7u(7lcw+^ut3a!H}A(`CCEg-jm+yZh7$SokZfZPId3&<@Xw}9LNatp{U z@V6~Mk6CeCs{p_;I}Uwuy-6~hE;xS1aX602aZMh__&9FIF+IlP*d52c_)8Ty ze#bFBu7~5+KKwxg_)!b$U{gn+IJ`Cj@BqdD%-;#9DWEf;3!p0i$H?CRFuprbb3hLO zZV|Kq;NaK_fbkyzwhev^BjoPu7QlUacyf{lzXF42X~onAOE6?Boep6$Xf4==IBjqS zgpi}u6^`giIi7+u^~)Icz)Nf3dr-U91X8K~oEP@4H0sB4v?e#Tff^exI4h|Wy7int zcWnpy8IT2^nbzvZJumdHHw**oi{YfM2hdR1*@XKj=`+o(DTzMlM~mZg+gkl77k{@0 z9UFFCqEHTnGJ0HuXBGzKdl|xuKZmoZNdL7 zKLcu?1usOrYuR@<586i4em305#_Q?O15SY0@aS1>YTusk5R3yB^-!UoPsj5eNo~)< N33O|d(|?);{tt|O)Z+jE literal 0 HcmV?d00001 diff --git a/apache-poi-2/src/main/resources/baeldung.docx b/apache-poi-2/src/main/resources/baeldung.docx new file mode 100644 index 0000000000000000000000000000000000000000..f0de4e057bee61081609a50af4db03d279db83e7 GIT binary patch literal 15598 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
    ^Bv$yaj+@1cVig4QR>XqM?@H4zM=X_D z?mrt9P5Tj!;Uu4w6xcHBV|zx_9u8;pGCU9rFr5p;%fQd@hftn6O)sq~j*f(`2_g}G z@IGVX^<|8Wc5w!$d!!wtpc&+*6VzDtRLgOJDT$#(ppYGziyVwXQi?i5^7C-o=6b}M zS9KQO)xMd;c9y<^OADXKI5B&i&rPb8R+YG|oeTFSH<$Y!6kMLn)Vhqw*lhNJ8i#O0YRUa7K!gOZ|WFcKTsMhB?Z!)UpC z>oSbdxA-o}`t?=($BaNg>0ZO?e?M6H_gnkVuYWmaDJ%I;1^+zg^|OMC*ZBRXV_&}l ze?9W@H+1cl`1D@~V19-FlV<%l7yu}Gr3?Q5NY}q=`juh(x2}7{KQ#S=Z~H6$SDNDA z_^Vge;_p5AnY8#T{8y^i-|*Ad)z9znUx{D8s`xcg{Xkr2Y z{wv)475>jp{?Bj|)}P>i1OUIH|LKT-Mk90lgx3GdEz3$myqY%vfcX07`8q?Cxqd7C EKZ`JklK=n! literal 0 HcmV?d00001 diff --git a/apache-poi-2/src/test/java/com/baeldung/poi/replacevariables/DocTextReplacerUnitTest.java b/apache-poi-2/src/test/java/com/baeldung/poi/replacevariables/DocTextReplacerUnitTest.java new file mode 100644 index 0000000000..0c3d80a354 --- /dev/null +++ b/apache-poi-2/src/test/java/com/baeldung/poi/replacevariables/DocTextReplacerUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.poi.replacevariables; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Arrays; + +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.hwpf.extractor.WordExtractor; +import org.junit.jupiter.api.Test; + +class DocTextReplacerUnitTest { + + @Test + void whenReplaceText_ThenTextReplaced() throws IOException { + new DocTextReplacer().replaceText(); + + String filePath = getClass().getClassLoader() + .getResource("baeldung.doc") + .getPath(); + try (FileInputStream fis = new FileInputStream(filePath); HWPFDocument document = new HWPFDocument(fis); WordExtractor extractor = new WordExtractor(document)) { + long occurrencesOfHello = Arrays.stream(extractor.getText() + .split("\\s+")) + .filter(s -> s.contains("Hello")) + .count(); + assertEquals(5, occurrencesOfHello); + } + } + +} diff --git a/apache-poi-2/src/test/java/com/baeldung/poi/replacevariables/DocxNaiveTextReplacerUnitTest.java b/apache-poi-2/src/test/java/com/baeldung/poi/replacevariables/DocxNaiveTextReplacerUnitTest.java new file mode 100644 index 0000000000..324e63eb51 --- /dev/null +++ b/apache-poi-2/src/test/java/com/baeldung/poi/replacevariables/DocxNaiveTextReplacerUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.poi.replacevariables; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Arrays; + +import org.apache.poi.xwpf.extractor.XWPFWordExtractor; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.junit.jupiter.api.Test; + +class DocxNaiveTextReplacerUnitTest { + + @Test + void whenReplaceText_ThenTextReplaced() throws IOException { + new DocxNaiveTextReplacer().replaceText(); + + String filePath = getClass().getClassLoader() + .getResource("baeldung-copy.docx") + .getPath(); + try (FileInputStream fis = new FileInputStream(filePath); XWPFDocument document = new XWPFDocument(fis); XWPFWordExtractor extractor = new XWPFWordExtractor(document)) { + long occurrencesOfHello = Arrays.stream(extractor.getText() + .split("\\s+")) + .filter(s -> s.contains("Hello")) + .count(); + assertTrue(occurrencesOfHello < 5); + } + } + +} diff --git a/apache-poi-2/src/test/java/com/baeldung/poi/replacevariables/DocxTestReplacerUnitTest.java b/apache-poi-2/src/test/java/com/baeldung/poi/replacevariables/DocxTestReplacerUnitTest.java new file mode 100644 index 0000000000..d09f6b003d --- /dev/null +++ b/apache-poi-2/src/test/java/com/baeldung/poi/replacevariables/DocxTestReplacerUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.poi.replacevariables; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Arrays; + +import org.apache.poi.xwpf.extractor.XWPFWordExtractor; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.junit.jupiter.api.Test; + +class DocxTestReplacerUnitTest { + + @Test + void whenReplaceText_ThenTextReplaced() throws IOException { + new DocxTextReplacer().replaceText(); + + String filePath = getClass().getClassLoader() + .getResource("baeldung.docx") + .getPath(); + try (FileInputStream fis = new FileInputStream(filePath); XWPFDocument document = new XWPFDocument(fis); XWPFWordExtractor extractor = new XWPFWordExtractor(document)) { + long occurrencesOfHello = Arrays.stream(extractor.getText() + .split("\\s+")) + .filter(s -> s.contains("Hello")) + .count(); + assertEquals(5, occurrencesOfHello); + } + } + +} From 3d15ed00203f57d24a5c3a0d0ccab3af6b400c2f Mon Sep 17 00:00:00 2001 From: sachin <56427366+sachin071287@users.noreply.github.com> Date: Wed, 31 May 2023 06:54:52 +0530 Subject: [PATCH 11/40] bael-5728 added code (#14010) * bael-5728 added code * bael-5728 added code * bael-5728 added code * bael-5728 code fix * bael-5728 code fix --------- Co-authored-by: Sachin kumar --- .../readresolvevsreadobject/Singleton.java | 21 +++++++ .../readresolvevsreadobject/User.java | 59 +++++++++++++++++++ .../SingletonUnitTest.java | 47 +++++++++++++++ .../readresolvevsreadobject/UserUnitTest.java | 52 ++++++++++++++++ 4 files changed, 179 insertions(+) create mode 100644 core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/Singleton.java create mode 100644 core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/User.java create mode 100644 core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/SingletonUnitTest.java create mode 100644 core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/UserUnitTest.java diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/Singleton.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/Singleton.java new file mode 100644 index 0000000000..91ee10dd6d --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/Singleton.java @@ -0,0 +1,21 @@ +package com.baeldung.readresolvevsreadobject; + +import java.io.ObjectStreamException; +import java.io.Serializable; + +public class Singleton implements Serializable { + + private static final long serialVersionUID = 1L; + private static Singleton INSTANCE = new Singleton(); + + private Singleton() { + } + + public static Singleton getInstance() { + return INSTANCE; + } + + private Object readResolve() throws ObjectStreamException { + return INSTANCE; + } +} diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/User.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/User.java new file mode 100644 index 0000000000..95aac0301e --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/User.java @@ -0,0 +1,59 @@ +package com.baeldung.readresolvevsreadobject; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +public class User implements Serializable { + + private static final long serialVersionUID = 3659932210257138726L; + private String userName; + private String password; + + 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; + } + + @Override + public String toString() { + return "User [userName=" + userName + ", password=" + password + "]"; + } + + public User() { + } + + public User(String userName, String password) { + super(); + this.userName = userName; + this.password = password; + } + + private void writeObject(ObjectOutputStream oos) throws IOException { + this.password = "xyz" + password; + oos.defaultWriteObject(); + } + + private void readObject(ObjectInputStream aInputStream) + throws ClassNotFoundException, IOException { + aInputStream.defaultReadObject(); + this.password = password.substring(3); + } + + private Object readResolve() { + return this; + } + +} diff --git a/core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/SingletonUnitTest.java b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/SingletonUnitTest.java new file mode 100644 index 0000000000..d5133ae976 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/SingletonUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.readresolvevsreadobject; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +public class SingletonUnitTest { + + @Test + public void testSingletonObj_withNoReadResolve() throws ClassNotFoundException, IOException { + // Serialization + FileOutputStream fos = new FileOutputStream("singleton.ser"); + ObjectOutputStream oos = new ObjectOutputStream(fos); + Singleton actualSingletonObject = Singleton.getInstance(); + oos.writeObject(actualSingletonObject); + + // Deserialization + Singleton deserializedSingletonObject = null; + FileInputStream fis = new FileInputStream("singleton.ser"); + ObjectInputStream ois = new ObjectInputStream(fis); + deserializedSingletonObject = (Singleton) ois.readObject(); + // remove readResolve() from Singleton class and uncomment this to test. + //assertNotEquals(actualSingletonObject.hashCode(), deserializedSingletonObject.hashCode()); + } + + @Test + public void testSingletonObj_withCustomReadResolve() + throws ClassNotFoundException, IOException { + // Serialization + FileOutputStream fos = new FileOutputStream("singleton.ser"); + ObjectOutputStream oos = new ObjectOutputStream(fos); + Singleton actualSingletonObject = Singleton.getInstance(); + oos.writeObject(actualSingletonObject); + + // Deserialization + Singleton deserializedSingletonObject = null; + FileInputStream fis = new FileInputStream("singleton.ser"); + ObjectInputStream ois = new ObjectInputStream(fis); + deserializedSingletonObject = (Singleton) ois.readObject(); + assertEquals(actualSingletonObject.hashCode(), deserializedSingletonObject.hashCode()); + } +} diff --git a/core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/UserUnitTest.java b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/UserUnitTest.java new file mode 100644 index 0000000000..ffd56d67e9 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/UserUnitTest.java @@ -0,0 +1,52 @@ +package com.baeldung.readresolvevsreadobject; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +public class UserUnitTest { + + @Test + public void testDeserializeObj_withOverriddenReadObject() + throws ClassNotFoundException, IOException { + // Serialization + FileOutputStream fos = new FileOutputStream("user.ser"); + ObjectOutputStream oos = new ObjectOutputStream(fos); + User acutalObject = new User("Sachin", "Kumar"); + oos.writeObject(acutalObject); + + // Deserialization + User deserializedUser = null; + FileInputStream fis = new FileInputStream("user.ser"); + ObjectInputStream ois = new ObjectInputStream(fis); + deserializedUser = (User) ois.readObject(); + assertNotEquals(deserializedUser.hashCode(), acutalObject.hashCode()); + assertEquals(deserializedUser.getUserName(), "Sachin"); + assertEquals(deserializedUser.getPassword(), "Kumar"); + } + + @Test + public void testDeserializeObj_withDefaultReadObject() + throws ClassNotFoundException, IOException { + // Serialization + FileOutputStream fos = new FileOutputStream("user.ser"); + ObjectOutputStream oos = new ObjectOutputStream(fos); + User acutalObject = new User("Sachin", "Kumar"); + oos.writeObject(acutalObject); + + // Deserialization + User deserializedUser = null; + FileInputStream fis = new FileInputStream("user.ser"); + ObjectInputStream ois = new ObjectInputStream(fis); + deserializedUser = (User) ois.readObject(); + assertNotEquals(deserializedUser.hashCode(), acutalObject.hashCode()); + assertEquals(deserializedUser.getUserName(), "Sachin"); + // remove readObject() from User class and uncomment this to test. + //assertEquals(deserializedUser.getPassword(), "xyzKumar"); + } +} From 9834fe1d212c5aeb745e1691527acca8f37bef93 Mon Sep 17 00:00:00 2001 From: Avin Buricha Date: Wed, 31 May 2023 08:45:00 +0530 Subject: [PATCH 12/40] BAEL-6409 | Article code (#14135) * BAEL-6409 | Article code * Compilation fix --- .../kafka/message/MessageWithKey.java | 106 ++++++++++++++ .../kafka/message/MessageWithKeyLiveTest.java | 130 ++++++++++++++++++ 2 files changed, 236 insertions(+) create mode 100644 apache-kafka-2/src/main/java/com/baeldung/kafka/message/MessageWithKey.java create mode 100644 apache-kafka-2/src/test/java/com/baeldung/kafka/message/MessageWithKeyLiveTest.java diff --git a/apache-kafka-2/src/main/java/com/baeldung/kafka/message/MessageWithKey.java b/apache-kafka-2/src/main/java/com/baeldung/kafka/message/MessageWithKey.java new file mode 100644 index 0000000000..b03c1e1adc --- /dev/null +++ b/apache-kafka-2/src/main/java/com/baeldung/kafka/message/MessageWithKey.java @@ -0,0 +1,106 @@ +package com.baeldung.kafka.message; + +import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import org.apache.kafka.clients.admin.Admin; +import org.apache.kafka.clients.admin.AdminClientConfig; +import org.apache.kafka.clients.admin.NewTopic; +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.producer.KafkaProducer; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.clients.producer.RecordMetadata; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.kafka.common.serialization.StringSerializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MessageWithKey { + + private static Logger logger = LoggerFactory.getLogger(MessageWithKey.class); + + private static String TOPIC = "baeldung"; + private static int PARTITIONS = 5; + private static short REPLICATION_FACTOR = 1; + + private static String MESSAGE_KEY = "message-key"; + + private static Admin admin; + private static KafkaProducer producer; + private static KafkaConsumer consumer; + + public static void main(String[] args) throws ExecutionException, InterruptedException { + setup(); + + publishMessagesWithoutKey(); + + consumeMessages(); + + publishMessagesWithKey(); + + consumeMessages(); + } + + private static void consumeMessages() { + consumer.subscribe(Arrays.asList(TOPIC)); + + ConsumerRecords records = consumer.poll(Duration.ofSeconds(5)); + for (ConsumerRecord record : records) { + logger.info("Key : {}, Value : {}", record.key(), record.value()); + } + } + + private static void publishMessagesWithKey() throws ExecutionException, InterruptedException { + for (int i = 1; i <= 10; i++) { + ProducerRecord record = new ProducerRecord<>(TOPIC, MESSAGE_KEY, String.valueOf(i)); + Future future = producer.send(record); + RecordMetadata metadata = future.get(); + + logger.info(String.valueOf(metadata.partition())); + } + } + + private static void publishMessagesWithoutKey() throws ExecutionException, InterruptedException { + for (int i = 1; i <= 10; i++) { + ProducerRecord record = new ProducerRecord<>(TOPIC, String.valueOf(i)); + Future future = producer.send(record); + RecordMetadata metadata = future.get(); + + logger.info(String.valueOf(metadata.partition())); + } + } + + private static void setup() { + Properties adminProperties = new Properties(); + adminProperties.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + + Properties producerProperties = new Properties(); + producerProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + producerProperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + producerProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + + Properties consumerProperties = new Properties(); + consumerProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, UUID.randomUUID() + .toString()); + + admin = Admin.create(adminProperties); + producer = new KafkaProducer<>(producerProperties); + consumer = new KafkaConsumer<>(consumerProperties); + + admin.createTopics(Collections.singleton(new NewTopic(TOPIC, PARTITIONS, REPLICATION_FACTOR))); + } + +} \ No newline at end of file diff --git a/apache-kafka-2/src/test/java/com/baeldung/kafka/message/MessageWithKeyLiveTest.java b/apache-kafka-2/src/test/java/com/baeldung/kafka/message/MessageWithKeyLiveTest.java new file mode 100644 index 0000000000..093dc629cb --- /dev/null +++ b/apache-kafka-2/src/test/java/com/baeldung/kafka/message/MessageWithKeyLiveTest.java @@ -0,0 +1,130 @@ +package com.baeldung.kafka.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import org.apache.kafka.clients.admin.Admin; +import org.apache.kafka.clients.admin.AdminClientConfig; +import org.apache.kafka.clients.admin.NewTopic; +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.producer.KafkaProducer; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.clients.producer.RecordMetadata; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.kafka.common.serialization.StringSerializer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; + +// This live test needs a Docker Daemon running so that a kafka container can be created + +@Testcontainers +public class MessageWithKeyLiveTest { + + private static String TOPIC = "baeldung"; + private static int PARTITIONS = 5; + private static short REPLICATION_FACTOR = 1; + + private static String MESSAGE_KEY = "message-key"; + private static String MESSAGE_VALUE = "Hello World"; + + private static Admin admin; + private static KafkaProducer producer; + private static KafkaConsumer consumer; + + @Container + private static final KafkaContainer KAFKA_CONTAINER = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest")); + + @BeforeAll + static void setup() { + KAFKA_CONTAINER.addExposedPort(9092); + + Properties adminProperties = new Properties(); + adminProperties.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers()); + + Properties producerProperties = new Properties(); + producerProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers()); + producerProperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + producerProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + + Properties consumerProperties = new Properties(); + consumerProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers()); + consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, UUID.randomUUID() + .toString()); + + admin = Admin.create(adminProperties); + producer = new KafkaProducer<>(producerProperties); + consumer = new KafkaConsumer<>(consumerProperties); + + admin.createTopics(Collections.singleton(new NewTopic(TOPIC, PARTITIONS, REPLICATION_FACTOR))); + } + + @AfterAll + static void destroy() { + KAFKA_CONTAINER.stop(); + } + + @Test + void givenAMessageWithKey_whenPublishedToKafkaAndConsumed_thenCheckForKey() throws ExecutionException, InterruptedException { + + ProducerRecord producerRecord = new ProducerRecord<>(TOPIC, MESSAGE_KEY, MESSAGE_VALUE); + Future future = producer.send(producerRecord); + + RecordMetadata metadata = future.get(); + + assertNotNull(metadata); + + consumer.subscribe(Arrays.asList(TOPIC)); + + ConsumerRecords records = consumer.poll(Duration.ofSeconds(5)); + for (ConsumerRecord consumerRecord : records) { + assertEquals(MESSAGE_KEY, consumerRecord.key()); + assertEquals(MESSAGE_VALUE, consumerRecord.value()); + } + } + + @Test + void givenAListOfMessageWithKeys_whenPublishedToKafka_thenCheckedIfPublishedToSamePartition() throws ExecutionException, InterruptedException { + + boolean isSamePartition = true; + int partition = 0; + + for (int i = 1; i <= 10; i++) { + ProducerRecord producerRecord = new ProducerRecord<>(TOPIC, MESSAGE_KEY, MESSAGE_VALUE); + Future future = producer.send(producerRecord); + + RecordMetadata metadata = future.get(); + + assertNotNull(metadata); + if (i == 1) { + partition = metadata.partition(); + } else { + if (partition != metadata.partition()) { + isSamePartition = false; + } + } + } + + assertTrue(isSamePartition); + } +} From 23917a110b4972ae4ce71d4c4418604b23ff28c5 Mon Sep 17 00:00:00 2001 From: Avin Buricha Date: Wed, 31 May 2023 08:53:46 +0530 Subject: [PATCH 13/40] BAEL-6416 | Article code (#14065) --- .../kafka/consumer/ConsumeFromBeginning.java | 81 +++++++++++++ .../ConsumeFromBeginningLiveTest.java | 109 ++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 apache-kafka-2/src/main/java/com/baeldung/kafka/consumer/ConsumeFromBeginning.java create mode 100644 apache-kafka-2/src/test/java/com/baeldung/kafka/consumer/ConsumeFromBeginningLiveTest.java diff --git a/apache-kafka-2/src/main/java/com/baeldung/kafka/consumer/ConsumeFromBeginning.java b/apache-kafka-2/src/main/java/com/baeldung/kafka/consumer/ConsumeFromBeginning.java new file mode 100644 index 0000000000..569c5aa9e9 --- /dev/null +++ b/apache-kafka-2/src/main/java/com/baeldung/kafka/consumer/ConsumeFromBeginning.java @@ -0,0 +1,81 @@ +package com.baeldung.kafka.consumer; + +import java.time.Duration; +import java.util.Arrays; +import java.util.Properties; +import java.util.UUID; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.producer.KafkaProducer; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.kafka.common.serialization.StringSerializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConsumeFromBeginning { + + private static Logger logger = LoggerFactory.getLogger(ConsumeFromBeginning.class); + + private static String TOPIC = "baeldung"; + private static int messagesInTopic = 10; + + private static KafkaProducer producer; + private static KafkaConsumer consumer; + + public static void main(String[] args) { + setup(); + + publishMessages(); + + consumeFromBeginning(); + } + + private static void consumeFromBeginning() { + consumer.subscribe(Arrays.asList(TOPIC)); + + ConsumerRecords records = consumer.poll(Duration.ofSeconds(10)); + + for (ConsumerRecord record : records) { + logger.info(record.value()); + } + + consumer.seekToBeginning(consumer.assignment()); + + records = consumer.poll(Duration.ofSeconds(10)); + + for (ConsumerRecord record : records) { + logger.info(record.value()); + } + } + + private static void publishMessages() { + for (int i = 1; i <= messagesInTopic; i++) { + ProducerRecord record = new ProducerRecord<>(TOPIC, String.valueOf(i)); + producer.send(record); + } + } + + private static void setup() { + Properties producerProperties = new Properties(); + producerProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + producerProperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + producerProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + + Properties consumerProperties = new Properties(); + consumerProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, UUID.randomUUID() + .toString()); + + producer = new KafkaProducer<>(producerProperties); + consumer = new KafkaConsumer<>(consumerProperties); + } + +} diff --git a/apache-kafka-2/src/test/java/com/baeldung/kafka/consumer/ConsumeFromBeginningLiveTest.java b/apache-kafka-2/src/test/java/com/baeldung/kafka/consumer/ConsumeFromBeginningLiveTest.java new file mode 100644 index 0000000000..6bfba1eca9 --- /dev/null +++ b/apache-kafka-2/src/test/java/com/baeldung/kafka/consumer/ConsumeFromBeginningLiveTest.java @@ -0,0 +1,109 @@ +package com.baeldung.kafka.consumer; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.time.Duration; +import java.util.Arrays; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.producer.KafkaProducer; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.kafka.common.serialization.StringSerializer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; + +// This live test needs a Docker Daemon running so that a kafka container can be created + +@Testcontainers +public class ConsumeFromBeginningLiveTest { + + private static Logger logger = LoggerFactory.getLogger(ConsumeFromBeginningLiveTest.class); + + private static String TOPIC = "baeldung"; + private static int messagesInTopic = 10; + + private static KafkaProducer producer; + private static KafkaConsumer consumer; + + @Container + private static final KafkaContainer KAFKA_CONTAINER = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest")); + + @BeforeAll + static void setup() { + KAFKA_CONTAINER.addExposedPort(9092); + + Properties producerProperties = new Properties(); + producerProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers()); + producerProperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + producerProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + + Properties consumerProperties = new Properties(); + consumerProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers()); + consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, UUID.randomUUID() + .toString()); + + producer = new KafkaProducer<>(producerProperties); + consumer = new KafkaConsumer<>(consumerProperties); + } + + private static void publishMessages() throws ExecutionException, InterruptedException { + for (int i = 1; i <= messagesInTopic; i++) { + ProducerRecord record = new ProducerRecord<>(TOPIC, String.valueOf(i)); + producer.send(record) + .get(); + } + } + + @AfterAll + static void destroy() { + KAFKA_CONTAINER.stop(); + } + + @Test + void givenMessages_whenConsumedFromBeginning_thenCheckIfConsumedFromBeginning() throws ExecutionException, InterruptedException { + + publishMessages(); + + consumer.subscribe(Arrays.asList(TOPIC)); + + ConsumerRecords records = consumer.poll(Duration.ofSeconds(10)); + + int messageCount = 0; + for (ConsumerRecord record : records) { + logger.info(record.value()); + messageCount++; + } + + assertEquals(messagesInTopic, messageCount); + + consumer.seekToBeginning(consumer.assignment()); + + records = consumer.poll(Duration.ofSeconds(10)); + + messageCount = 0; + for (ConsumerRecord record : records) { + logger.info(record.value()); + messageCount++; + } + + assertEquals(messagesInTopic, messageCount); + } +} From 920214f38dd07af14eea79682e16572a41118054 Mon Sep 17 00:00:00 2001 From: Kasra Madadipouya Date: Wed, 31 May 2023 13:40:49 +0200 Subject: [PATCH 14/40] JAVA-17164 update config and discovery services to use Spring Boot 2.7.X (#13967) --- .../book-service.properties | 2 + .../application-config/gateway.properties | 18 +---- .../rating-service.properties | 2 + .../spring-cloud-bootstrap/config/pom.xml | 8 +-- .../bootstrap/config/ConfigApplication.java | 4 +- .../bootstrap/config/SecurityConfig.java | 42 +++++++---- .../spring-cloud-bootstrap/discovery/pom.xml | 14 ++-- .../bootstrap/discovery/SecurityConfig.java | 2 +- .../spring-cloud-bootstrap/gateway/pom.xml | 24 ++++--- .../bootstrap/gateway/ErrorPageConfig.java | 6 +- .../bootstrap/gateway/GatewayApplication.java | 67 +----------------- .../bootstrap/gateway/SecurityConfig.java | 70 ++++++++++++------- .../bootstrap/gateway/SessionConfig.java | 9 ++- .../gateway/client/book/BooksClient.java | 5 +- .../gateway/client/rating/RatingsClient.java | 9 ++- .../filter/SessionSavingPreFilter.java | 25 +++++++ .../filter/SessionSavingZuulPreFilter.java | 47 ------------- .../src/main/resources/bootstrap.properties | 2 + .../spring-cloud-bootstrap/pom.xml | 1 - .../spring-cloud-bootstrap/svc-book/pom.xml | 20 ++++-- .../svcbook/BookServiceApplication.java | 43 +----------- .../cloud/bootstrap/svcbook/CookieConfig.java | 16 +++++ .../bootstrap/svcbook/SecurityConfig.java | 35 +++++----- .../bootstrap/svcbook/book/BookService.java | 10 +-- .../src/main/resources/bootstrap.properties | 2 + .../spring-cloud-bootstrap/svc-rating/pom.xml | 28 +++++--- .../bootstrap/svcrating/CookieConfig.java | 16 +++++ .../svcrating/RatingServiceApplication.java | 57 +-------------- .../bootstrap/svcrating/SecurityConfig.java | 50 ++++++------- .../bootstrap/svcrating/SessionConfig.java | 20 +++--- .../rating/RatingCacheRepository.java | 6 +- .../svcrating/rating/RatingService.java | 22 +++--- .../src/main/resources/bootstrap.properties | 2 + .../spring-cloud-bootstrap/zipkin/README.md | 19 +++++ .../zipkin/docker-compose.yml | 6 ++ .../spring-cloud-bootstrap/zipkin/pom.xml | 53 -------------- .../bootstrap/zipkin/ZipkinApplication.java | 15 ---- .../src/main/resources/bootstrap.properties | 7 -- .../zipkin/src/main/resources/logback.xml | 13 ---- .../java/com/baeldung/SpringContextTest.java | 17 ----- 40 files changed, 329 insertions(+), 485 deletions(-) create mode 100644 spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/filter/SessionSavingPreFilter.java delete mode 100644 spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/filter/SessionSavingZuulPreFilter.java create mode 100644 spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/CookieConfig.java create mode 100644 spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/CookieConfig.java create mode 100644 spring-cloud-modules/spring-cloud-bootstrap/zipkin/README.md create mode 100644 spring-cloud-modules/spring-cloud-bootstrap/zipkin/docker-compose.yml delete mode 100644 spring-cloud-modules/spring-cloud-bootstrap/zipkin/pom.xml delete mode 100644 spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java delete mode 100644 spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties delete mode 100644 spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/main/resources/logback.xml delete mode 100644 spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-cloud-modules/spring-cloud-bootstrap/application-config/book-service.properties b/spring-cloud-modules/spring-cloud-bootstrap/application-config/book-service.properties index 49f7d1ed91..2ea30b9ab7 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/application-config/book-service.properties +++ b/spring-cloud-modules/spring-cloud-bootstrap/application-config/book-service.properties @@ -18,3 +18,5 @@ spring.redis.port=6379 spring.sleuth.sampler.percentage=1.0 spring.sleuth.web.skipPattern=(^cleanup.*) + +spring.zipkin.baseUrl=http://localhost:9411 diff --git a/spring-cloud-modules/spring-cloud-bootstrap/application-config/gateway.properties b/spring-cloud-modules/spring-cloud-bootstrap/application-config/gateway.properties index e9e593284c..42e114450d 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/application-config/gateway.properties +++ b/spring-cloud-modules/spring-cloud-bootstrap/application-config/gateway.properties @@ -6,25 +6,13 @@ eureka.client.registryFetchIntervalSeconds = 5 management.security.sessions=always -zuul.routes.book-service.path=/book-service/** -zuul.routes.book-service.sensitive-headers=Set-Cookie,Authorization -hystrix.command.book-service.execution.isolation.thread.timeoutInMilliseconds=600000 - -zuul.routes.rating-service.path=/rating-service/** -zuul.routes.rating-service.sensitive-headers=Set-Cookie,Authorization -hystrix.command.rating-service.execution.isolation.thread.timeoutInMilliseconds=600000 - -zuul.routes.discovery.path=/discovery/** -zuul.routes.discovery.sensitive-headers=Set-Cookie,Authorization -zuul.routes.discovery.url=http://localhost:8082 -hystrix.command.discovery.execution.isolation.thread.timeoutInMilliseconds=600000 - logging.level.org.springframework.web.=debug logging.level.org.springframework.security=debug -logging.level.org.springframework.cloud.netflix.zuul=debug spring.redis.host=localhost spring.redis.port=6379 spring.sleuth.sampler.percentage=1.0 -spring.sleuth.web.skipPattern=(^cleanup.*|.+favicon.*) \ No newline at end of file +spring.sleuth.web.skipPattern=(^cleanup.*|.+favicon.*) + +spring.zipkin.baseUrl=http://localhost:9411 diff --git a/spring-cloud-modules/spring-cloud-bootstrap/application-config/rating-service.properties b/spring-cloud-modules/spring-cloud-bootstrap/application-config/rating-service.properties index b7cbb6fbd6..059b87e4e7 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/application-config/rating-service.properties +++ b/spring-cloud-modules/spring-cloud-bootstrap/application-config/rating-service.properties @@ -18,3 +18,5 @@ spring.redis.port=6379 spring.sleuth.sampler.percentage=1.0 spring.sleuth.web.skipPattern=(^cleanup.*) + +spring.zipkin.baseUrl=http://localhost:9411 diff --git a/spring-cloud-modules/spring-cloud-bootstrap/config/pom.xml b/spring-cloud-modules/spring-cloud-bootstrap/config/pom.xml index 6c9c3c5374..c1be447822 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/config/pom.xml +++ b/spring-cloud-modules/spring-cloud-bootstrap/config/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../../../parent-boot-1 + ../../../parent-boot-2 @@ -33,7 +33,7 @@ org.springframework.cloud - spring-cloud-starter-eureka + spring-cloud-starter-netflix-eureka-client org.springframework.boot @@ -42,7 +42,7 @@ - Brixton.SR7 + 2021.0.7 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/config/src/main/java/com/baeldung/spring/cloud/bootstrap/config/ConfigApplication.java b/spring-cloud-modules/spring-cloud-bootstrap/config/src/main/java/com/baeldung/spring/cloud/bootstrap/config/ConfigApplication.java index 847c86f881..c3e04c4b54 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/config/src/main/java/com/baeldung/spring/cloud/bootstrap/config/ConfigApplication.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/config/src/main/java/com/baeldung/spring/cloud/bootstrap/config/ConfigApplication.java @@ -2,12 +2,12 @@ package com.baeldung.spring.cloud.bootstrap.config; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.config.server.EnableConfigServer; -import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableConfigServer -@EnableEurekaClient +@EnableDiscoveryClient public class ConfigApplication { public static void main(String[] args) { SpringApplication.run(ConfigApplication.class, args); diff --git a/spring-cloud-modules/spring-cloud-bootstrap/config/src/main/java/com/baeldung/spring/cloud/bootstrap/config/SecurityConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/config/src/main/java/com/baeldung/spring/cloud/bootstrap/config/SecurityConfig.java index ef1d7b0b78..d563052baa 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/config/src/main/java/com/baeldung/spring/cloud/bootstrap/config/SecurityConfig.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/config/src/main/java/com/baeldung/spring/cloud/bootstrap/config/SecurityConfig.java @@ -1,23 +1,41 @@ package com.baeldung.spring.cloud.bootstrap.config; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.context.annotation.Bean; 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.core.userdetails.User; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; -@Configuration @EnableWebSecurity -public class SecurityConfig extends WebSecurityConfigurerAdapter { +public class SecurityConfig { - @Autowired - public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication().withUser("configUser").password("configPassword").roles("SYSTEM"); + @Bean + public InMemoryUserDetailsManager userDetailsService(BCryptPasswordEncoder bCryptPasswordEncoder) { + InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); + manager.createUser(User.withUsername("configUser") + .password(bCryptPasswordEncoder.encode("configPassword")) + .roles("SYSTEM") + .build()); + return manager; } - @Override - protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests().anyRequest().hasRole("SYSTEM").and().httpBasic().and().csrf().disable(); + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http.authorizeRequests() + .anyRequest() + .hasRole("SYSTEM") + .and() + .httpBasic() + .and() + .csrf() + .disable(); + return http.build(); + } + + @Bean + public BCryptPasswordEncoder encoder() { + return new BCryptPasswordEncoder(); } } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/discovery/pom.xml b/spring-cloud-modules/spring-cloud-bootstrap/discovery/pom.xml index fb06c6052b..28c1a741a6 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/discovery/pom.xml +++ b/spring-cloud-modules/spring-cloud-bootstrap/discovery/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../../../parent-boot-1 + ../../../parent-boot-2 @@ -33,7 +33,11 @@ org.springframework.cloud - spring-cloud-starter-eureka-server + spring-cloud-starter-bootstrap + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-server org.springframework.boot @@ -41,7 +45,7 @@ org.springframework.session - spring-session + spring-session-data-redis org.springframework.boot @@ -50,7 +54,7 @@ - Edgware.SR5 + 2021.0.7 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/discovery/src/main/java/com/baeldung/spring/cloud/bootstrap/discovery/SecurityConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/discovery/src/main/java/com/baeldung/spring/cloud/bootstrap/discovery/SecurityConfig.java index a89faba962..fa389ec6a3 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/discovery/src/main/java/com/baeldung/spring/cloud/bootstrap/discovery/SecurityConfig.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/discovery/src/main/java/com/baeldung/spring/cloud/bootstrap/discovery/SecurityConfig.java @@ -17,7 +17,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication().withUser("discUser").password("discPassword").roles("SYSTEM"); + auth.inMemoryAuthentication().withUser("discUser").password("{noop}discPassword").roles("SYSTEM"); } @Override diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/pom.xml b/spring-cloud-modules/spring-cloud-bootstrap/gateway/pom.xml index e1041516c4..fa6735199f 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/pom.xml +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../../../parent-boot-1 + ../../../parent-boot-2 @@ -33,11 +33,15 @@ org.springframework.cloud - spring-cloud-starter-eureka + spring-cloud-starter-bootstrap org.springframework.cloud - spring-cloud-starter-zuul + spring-cloud-starter-netflix-eureka-client + + + org.springframework.cloud + spring-cloud-starter-gateway org.springframework.boot @@ -45,7 +49,7 @@ org.springframework.session - spring-session + spring-session-data-redis org.springframework.boot @@ -53,11 +57,15 @@ org.springframework.cloud - spring-cloud-starter-zipkin + spring-cloud-starter-sleuth org.springframework.cloud - spring-cloud-starter-feign + spring-cloud-sleuth-zipkin + + + org.springframework.cloud + spring-cloud-starter-openfeign @@ -97,7 +105,7 @@ - Dalston.RELEASE + 2021.0.7 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/ErrorPageConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/ErrorPageConfig.java index 67d172d3cd..b1fa7ce0bb 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/ErrorPageConfig.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/ErrorPageConfig.java @@ -1,8 +1,8 @@ package com.baeldung.spring.cloud.bootstrap.gateway; -import org.springframework.boot.web.servlet.ErrorPage; -import org.springframework.boot.web.servlet.ErrorPageRegistrar; -import org.springframework.boot.web.servlet.ErrorPageRegistry; +import org.springframework.boot.web.server.ErrorPage; +import org.springframework.boot.web.server.ErrorPageRegistrar; +import org.springframework.boot.web.server.ErrorPageRegistry; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java index 8fc75e1ff6..6adda92c25 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java @@ -1,76 +1,15 @@ package com.baeldung.spring.cloud.bootstrap.gateway; -import com.netflix.appinfo.InstanceInfo; -import com.netflix.discovery.EurekaClient; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.loadbalancer.LoadBalanced; -import org.springframework.cloud.netflix.eureka.EnableEurekaClient; -import org.springframework.cloud.netflix.feign.EnableFeignClients; -import org.springframework.cloud.netflix.ribbon.RibbonClientSpecification; -import org.springframework.cloud.netflix.ribbon.SpringClientFactory; -import org.springframework.cloud.netflix.zuul.EnableZuulProxy; -import org.springframework.cloud.sleuth.metric.SpanMetricReporter; -import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter; -import org.springframework.cloud.sleuth.zipkin.ZipkinProperties; -import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter; -import org.springframework.context.annotation.Bean; -import org.springframework.web.client.RestTemplate; -import zipkin.Span; - -import java.util.ArrayList; -import java.util.List; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication -@EnableZuulProxy -@EnableEurekaClient @EnableFeignClients +@EnableDiscoveryClient public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } - - @Autowired(required = false) - private List configurations = new ArrayList<>(); - @Autowired - private EurekaClient eurekaClient; - @Autowired - private SpanMetricReporter spanMetricReporter; - @Autowired - private ZipkinProperties zipkinProperties; - @Value("${spring.sleuth.web.skipPattern}") - private String skipPattern; - - @Bean - @LoadBalanced - RestTemplate restTemplate() { - return new RestTemplate(); - } - - @Bean - public SpringClientFactory springClientFactory() { - SpringClientFactory factory = new SpringClientFactory(); - factory.setConfigurations(this.configurations); - return factory; - } - - @Bean - public ZipkinSpanReporter makeZipkinSpanReporter() { - return new ZipkinSpanReporter() { - private HttpZipkinSpanReporter delegate; - private String baseUrl; - - @Override - public void report(Span span) { - InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false); - if (baseUrl == null || !instance.getHomePageUrl().equals(baseUrl)) { - baseUrl = instance.getHomePageUrl(); - } - delegate = new HttpZipkinSpanReporter(new RestTemplate(), baseUrl, zipkinProperties.getFlushInterval(), spanMetricReporter); - if (!span.name.matches(skipPattern)) delegate.report(span); - } - }; - } } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java index d56be699e6..088fdd01f7 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java @@ -1,37 +1,59 @@ package com.baeldung.spring.cloud.bootstrap.gateway; -import org.springframework.beans.factory.annotation.Autowired; +import static org.springframework.security.config.Customizer.withDefaults; + +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.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.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.server.SecurityWebFilterChain; +import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler; -@EnableWebSecurity +@EnableWebFluxSecurity @Configuration -public class SecurityConfig extends WebSecurityConfigurerAdapter { +public class SecurityConfig { - @Autowired - public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication() - .withUser("user").password("password").roles("USER") - .and() - .withUser("admin").password("admin").roles("ADMIN"); + @Bean + public MapReactiveUserDetailsService userDetailsService() { + UserDetails user = User.withUsername("user") + .password(passwordEncoder().encode("password")) + .roles("USER") + .build(); + UserDetails adminUser = User.withUsername("admin") + .password(passwordEncoder().encode("admin")) + .roles("ADMIN") + .build(); + return new MapReactiveUserDetailsService(user, adminUser); } - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .formLogin() - .defaultSuccessUrl("/home/index.html", true) + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + http.formLogin() + .authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/home/index.html")) .and() - .authorizeRequests() - .antMatchers("/book-service/**", "/rating-service/**", "/login*", "/").permitAll() - .antMatchers("/eureka/**").hasRole("ADMIN") - .anyRequest().authenticated() + .authorizeExchange() + .pathMatchers("/book-service/**", "/rating-service/**", "/login*", "/") + .permitAll() + .pathMatchers("/eureka/**") + .hasRole("ADMIN") + .anyExchange() + .authenticated() .and() - .logout() + .logout() .and() - .csrf().disable(); + .csrf() + .disable() + .httpBasic(withDefaults()); + return http.build(); } } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SessionConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SessionConfig.java index 14f7deb770..498c780f65 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SessionConfig.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SessionConfig.java @@ -1,11 +1,10 @@ package com.baeldung.spring.cloud.bootstrap.gateway; import org.springframework.context.annotation.Configuration; -import org.springframework.session.data.redis.RedisFlushMode; -import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; -import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer; +import org.springframework.session.data.redis.config.annotation.web.server.EnableRedisWebSession; @Configuration -@EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE) -public class SessionConfig extends AbstractHttpSessionApplicationInitializer { +@EnableRedisWebSession +public class SessionConfig { + } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/book/BooksClient.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/book/BooksClient.java index f60f65d23c..8fd235b3dc 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/book/BooksClient.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/book/BooksClient.java @@ -1,7 +1,6 @@ package com.baeldung.spring.cloud.bootstrap.gateway.client.book; -import org.springframework.cloud.netflix.feign.FeignClient; -import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -9,6 +8,6 @@ import org.springframework.web.bind.annotation.RequestMethod; @FeignClient(value = "book-service") public interface BooksClient { - @RequestMapping(value = "/books/{bookId}", method = {RequestMethod.GET}) + @RequestMapping(value = "/books/{bookId}", method = { RequestMethod.GET }) Book getBookById(@PathVariable("bookId") Long bookId); } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/rating/RatingsClient.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/rating/RatingsClient.java index 9728111c5e..d04ba85082 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/rating/RatingsClient.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/client/rating/RatingsClient.java @@ -1,17 +1,16 @@ package com.baeldung.spring.cloud.bootstrap.gateway.client.rating; -import org.springframework.cloud.netflix.feign.FeignClient; -import org.springframework.web.bind.annotation.GetMapping; +import java.util.List; + +import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -import java.util.List; - @FeignClient(value = "rating-service") public interface RatingsClient { - @RequestMapping(value = "/ratings", method = {RequestMethod.GET}) + @RequestMapping(value = "/ratings", method = { RequestMethod.GET }) List getRatingsByBookId(@RequestParam("bookId") Long bookId, @RequestHeader("Cookie") String session); } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/filter/SessionSavingPreFilter.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/filter/SessionSavingPreFilter.java new file mode 100644 index 0000000000..bf10152318 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/filter/SessionSavingPreFilter.java @@ -0,0 +1,25 @@ +package com.baeldung.spring.cloud.bootstrap.gateway.filter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; + +import reactor.core.publisher.Mono; + +@Component +public class SessionSavingPreFilter implements GlobalFilter { + + private static final Logger logger = LoggerFactory.getLogger(SessionSavingPreFilter.class); + + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + return exchange.getSession() + .flatMap(session -> { + logger.debug("SessionId: {}", session.getId()); + return chain.filter(exchange); + }); + } +} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/filter/SessionSavingZuulPreFilter.java b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/filter/SessionSavingZuulPreFilter.java deleted file mode 100644 index 1c90ba2e12..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/filter/SessionSavingZuulPreFilter.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.baeldung.spring.cloud.bootstrap.gateway.filter; - -import com.netflix.zuul.ZuulFilter; -import com.netflix.zuul.context.RequestContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.session.Session; -import org.springframework.session.SessionRepository; -import org.springframework.stereotype.Component; - -import javax.servlet.http.HttpSession; - -@Component -public class SessionSavingZuulPreFilter extends ZuulFilter { - - private Logger log = LoggerFactory.getLogger(this.getClass()); - - @Autowired - private SessionRepository repository; - - @Override - public boolean shouldFilter() { - return true; - } - - @Override - public Object run() { - RequestContext context = RequestContext.getCurrentContext(); - HttpSession httpSession = context.getRequest().getSession(); - Session session = repository.getSession(httpSession.getId()); - - context.addZuulRequestHeader("Cookie", "SESSION=" + httpSession.getId()); - log.info("ZuulPreFilter session proxy: {}", session.getId()); - return null; - } - - @Override - public String filterType() { - return "pre"; - } - - @Override - public int filterOrder() { - return 0; - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/bootstrap.properties b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/bootstrap.properties index 43491ff36b..1c90ca9db0 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/bootstrap.properties +++ b/spring-cloud-modules/spring-cloud-bootstrap/gateway/src/main/resources/bootstrap.properties @@ -3,5 +3,7 @@ spring.cloud.config.discovery.service-id=config spring.cloud.config.discovery.enabled=true spring.cloud.config.username=configUser spring.cloud.config.password=configPassword +spring.cloud.gateway.discovery.locator.enabled=true +spring.cloud.gateway.discovery.locator.lowerCaseServiceId=true eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/ \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/pom.xml b/spring-cloud-modules/spring-cloud-bootstrap/pom.xml index 1e97082db1..e7fe7e7485 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/pom.xml +++ b/spring-cloud-modules/spring-cloud-bootstrap/pom.xml @@ -20,7 +20,6 @@ gateway svc-book svc-rating - zipkin customer-service order-service diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-book/pom.xml b/spring-cloud-modules/spring-cloud-bootstrap/svc-book/pom.xml index b1aa205af5..c973968a70 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/svc-book/pom.xml +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-book/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../../../parent-boot-1 + ../../../parent-boot-2 @@ -34,7 +34,11 @@ org.springframework.cloud - spring-cloud-starter-eureka + spring-cloud-starter-bootstrap + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client org.springframework.boot @@ -46,7 +50,7 @@ org.springframework.session - spring-session + spring-session-data-redis org.springframework.boot @@ -63,12 +67,16 @@ org.springframework.cloud - spring-cloud-starter-zipkin + spring-cloud-starter-sleuth + + + org.springframework.cloud + spring-cloud-sleuth-zipkin - Dalston.RELEASE + 2021.0.7 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java b/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java index d787b5e407..8b1eab7885 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java @@ -1,53 +1,14 @@ package com.baeldung.spring.cloud.bootstrap.svcbook; -import com.netflix.appinfo.InstanceInfo; -import com.netflix.discovery.EurekaClient; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.netflix.eureka.EnableEurekaClient; -import org.springframework.cloud.sleuth.metric.SpanMetricReporter; -import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter; -import org.springframework.cloud.sleuth.zipkin.ZipkinProperties; -import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter; -import org.springframework.context.annotation.Bean; -import org.springframework.web.client.RestTemplate; - -import zipkin.Span; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication -@EnableEurekaClient +@EnableDiscoveryClient public class BookServiceApplication { - @Autowired - private EurekaClient eurekaClient; - @Autowired - private SpanMetricReporter spanMetricReporter; - @Autowired - private ZipkinProperties zipkinProperties; - @Value("${spring.sleuth.web.skipPattern}") - private String skipPattern; - public static void main(String[] args) { SpringApplication.run(BookServiceApplication.class, args); } - - @Bean - public ZipkinSpanReporter makeZipkinSpanReporter() { - return new ZipkinSpanReporter() { - private HttpZipkinSpanReporter delegate; - private String baseUrl; - - @Override - public void report(Span span) { - InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false); - if (baseUrl == null || !instance.getHomePageUrl().equals(baseUrl)) { - baseUrl = instance.getHomePageUrl(); - } - delegate = new HttpZipkinSpanReporter(new RestTemplate(), baseUrl, zipkinProperties.getFlushInterval(), spanMetricReporter); - if (!span.name.matches(skipPattern)) delegate.report(span); - } - }; - } } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/CookieConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/CookieConfig.java new file mode 100644 index 0000000000..99696836c1 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/CookieConfig.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.cloud.bootstrap.svcbook; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.session.web.http.DefaultCookieSerializer; + +@Configuration +public class CookieConfig { + + @Bean + public DefaultCookieSerializer cookieSerializer() { + DefaultCookieSerializer serializer = new DefaultCookieSerializer(); + serializer.setUseBase64Encoding(false); + return serializer; + } +} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/SecurityConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/SecurityConfig.java index 6aa996c575..0b9520c976 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/SecurityConfig.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/SecurityConfig.java @@ -1,36 +1,37 @@ package com.baeldung.spring.cloud.bootstrap.svcbook; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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.web.SecurityFilterChain; @EnableWebSecurity @Configuration -public class SecurityConfig extends WebSecurityConfigurerAdapter { +public class SecurityConfig { @Autowired - public void configureGlobal1(AuthenticationManagerBuilder auth) throws Exception { - //try in memory auth with no users to support the case that this will allow for users that are logged in to go anywhere + public void registerAuthProvider(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication(); } - @Override - protected void configure(HttpSecurity http) throws Exception { - http.httpBasic() + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + return http.authorizeHttpRequests((auth) -> auth.antMatchers(HttpMethod.GET, "/books") + .permitAll() + .antMatchers(HttpMethod.GET, "/books/*") + .permitAll() + .antMatchers(HttpMethod.POST, "/books") + .hasRole("ADMIN") + .antMatchers(HttpMethod.PATCH, "/books/*") + .hasRole("ADMIN") + .antMatchers(HttpMethod.DELETE, "/books/*") + .hasRole("ADMIN")) + .csrf() .disable() - .authorizeRequests() - .antMatchers(HttpMethod.GET, "/books").permitAll() - .antMatchers(HttpMethod.GET, "/books/*").permitAll() - .antMatchers(HttpMethod.POST, "/books").hasRole("ADMIN") - .antMatchers(HttpMethod.PATCH, "/books/*").hasRole("ADMIN") - .antMatchers(HttpMethod.DELETE, "/books/*").hasRole("ADMIN") - .anyRequest().authenticated() - .and() - .csrf() - .disable(); + .build(); } } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java b/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java index 106fdad5d9..4ee3112049 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java @@ -2,7 +2,6 @@ package com.baeldung.spring.cloud.bootstrap.svcbook.book; import java.util.List; import java.util.Map; -import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -23,8 +22,8 @@ public class BookService { } public Book findBookById(Long bookId) { - return Optional.ofNullable(bookRepository.findOne(bookId)) - .orElseThrow(() -> new BookNotFoundException("Book not found. ID: " + bookId)); + return bookRepository.findById(bookId) + .orElseThrow(() -> new BookNotFoundException(String.format("Book not found. ID: %s", bookId))); } @Transactional(propagation = Propagation.REQUIRED) @@ -37,7 +36,7 @@ public class BookService { @Transactional(propagation = Propagation.REQUIRED) public void deleteBook(Long bookId) { - bookRepository.delete(bookId); + bookRepository.deleteById(bookId); } @Transactional(propagation = Propagation.REQUIRED) @@ -60,7 +59,8 @@ public class BookService { public Book updateBook(Book book, Long bookId) { Preconditions.checkNotNull(book); Preconditions.checkState(book.getId() == bookId); - Preconditions.checkNotNull(bookRepository.findOne(bookId)); + Preconditions.checkArgument(bookRepository.findById(bookId) + .isPresent()); return bookRepository.save(book); } } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties b/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties index 481cdc182c..a50048c671 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties @@ -3,5 +3,7 @@ spring.cloud.config.discovery.service-id=config spring.cloud.config.discovery.enabled=true spring.cloud.config.username=configUser spring.cloud.config.password=configPassword +spring.cloud.gateway.discovery.locator.enabled=true +spring.cloud.gateway.discovery.locator.lowerCaseServiceId=true eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/ \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/pom.xml b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/pom.xml index 336c1ff2c6..29ebb4c4bc 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/pom.xml +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../../../parent-boot-1 + ../../../parent-boot-2 @@ -34,7 +34,11 @@ org.springframework.cloud - spring-cloud-starter-eureka + spring-cloud-starter-bootstrap + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client org.springframework.boot @@ -46,7 +50,7 @@ org.springframework.session - spring-session + spring-session-data-redis org.springframework.boot @@ -58,25 +62,29 @@ org.springframework.cloud - spring-cloud-starter-hystrix + spring-cloud-starter-circuitbreaker-resilience4j org.springframework.boot spring-boot-starter-actuator + + org.springframework.cloud + spring-cloud-starter-sleuth + + + org.springframework.cloud + spring-cloud-sleuth-zipkin + com.h2database h2 runtime - - org.springframework.cloud - spring-cloud-starter-zipkin - - Dalston.RELEASE + 2021.0.7 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/CookieConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/CookieConfig.java new file mode 100644 index 0000000000..9774c18568 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/CookieConfig.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.cloud.bootstrap.svcrating; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.session.web.http.DefaultCookieSerializer; + +@Configuration +public class CookieConfig { + + @Bean + public DefaultCookieSerializer cookieSerializer() { + DefaultCookieSerializer serializer = new DefaultCookieSerializer(); + serializer.setUseBase64Encoding(false); + return serializer; + } +} \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java index 5a94f19472..1774407d26 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java @@ -1,69 +1,18 @@ package com.baeldung.spring.cloud.bootstrap.svcrating; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.netflix.eureka.EnableEurekaClient; -import org.springframework.cloud.netflix.hystrix.EnableHystrix; -import org.springframework.cloud.sleuth.metric.SpanMetricReporter; -import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter; -import org.springframework.cloud.sleuth.zipkin.ZipkinProperties; -import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.annotation.AdviceMode; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Primary; import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; import org.springframework.transaction.annotation.EnableTransactionManagement; -import org.springframework.web.client.RestTemplate; - -import com.netflix.appinfo.InstanceInfo; -import com.netflix.discovery.EurekaClient; -import com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect; - -import zipkin.Span; @SpringBootApplication -@EnableEurekaClient -@EnableHystrix -@EnableTransactionManagement(order=Ordered.LOWEST_PRECEDENCE, mode=AdviceMode.ASPECTJ) +@EnableDiscoveryClient +@EnableTransactionManagement(order = Ordered.LOWEST_PRECEDENCE, mode = AdviceMode.ASPECTJ) public class RatingServiceApplication { - @Autowired - private EurekaClient eurekaClient; - @Autowired - private SpanMetricReporter spanMetricReporter; - @Autowired - private ZipkinProperties zipkinProperties; - @Value("${spring.sleuth.web.skipPattern}") - private String skipPattern; public static void main(String[] args) { SpringApplication.run(RatingServiceApplication.class, args); } - - @Bean - public ZipkinSpanReporter makeZipkinSpanReporter() { - return new ZipkinSpanReporter() { - private HttpZipkinSpanReporter delegate; - private String baseUrl; - - @Override - public void report(Span span) { - InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false); - if (baseUrl == null || !instance.getHomePageUrl().equals(baseUrl)) { - baseUrl = instance.getHomePageUrl(); - } - delegate = new HttpZipkinSpanReporter(new RestTemplate(), baseUrl, zipkinProperties.getFlushInterval(), spanMetricReporter); - if (!span.name.matches(skipPattern)) delegate.report(span); - } - }; - } - - @Bean - @Primary - @Order(value=Ordered.HIGHEST_PRECEDENCE) - public HystrixCommandAspect hystrixAspect() { - return new HystrixCommandAspect(); - } } \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SecurityConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SecurityConfig.java index 9b6afc8059..f470946e1d 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SecurityConfig.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SecurityConfig.java @@ -1,39 +1,41 @@ package com.baeldung.spring.cloud.bootstrap.svcrating; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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.core.userdetails.UserDetailsService; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; @EnableWebSecurity @Configuration -public class SecurityConfig extends WebSecurityConfigurerAdapter { +public class SecurityConfig { - @Autowired - public void configureGlobal1(AuthenticationManagerBuilder auth) throws Exception { - //try in memory auth with no users to support the case that this will allow for users that are logged in to go anywhere - auth.inMemoryAuthentication(); + @Bean + public UserDetailsService users() { + return new InMemoryUserDetailsManager(); } - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .authorizeRequests() - .regexMatchers("^/ratings\\?bookId.*$").authenticated() - .antMatchers(HttpMethod.POST,"/ratings").authenticated() - .antMatchers(HttpMethod.PATCH,"/ratings/*").hasRole("ADMIN") - .antMatchers(HttpMethod.DELETE,"/ratings/*").hasRole("ADMIN") - .antMatchers(HttpMethod.GET,"/ratings").hasRole("ADMIN") - .antMatchers(HttpMethod.GET,"/hystrix").authenticated() - .anyRequest().authenticated() + @Bean + public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { + return httpSecurity.authorizeHttpRequests((auth) -> auth.regexMatchers("^/ratings\\?bookId.*$") + .authenticated() + .antMatchers(HttpMethod.POST, "/ratings") + .authenticated() + .antMatchers(HttpMethod.PATCH, "/ratings/*") + .hasRole("ADMIN") + .antMatchers(HttpMethod.DELETE, "/ratings/*") + .hasRole("ADMIN") + .antMatchers(HttpMethod.GET, "/ratings") + .hasRole("ADMIN") + .anyRequest() + .authenticated()) + .httpBasic() .and() - .httpBasic().and() - .csrf() - .disable(); - - + .csrf() + .disable() + .build(); } } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SessionConfig.java b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SessionConfig.java index 6e8fcd10d4..c0e067026d 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SessionConfig.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SessionConfig.java @@ -5,24 +5,24 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.env.Environment; -import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer; @Configuration @EnableRedisHttpSession public class SessionConfig extends AbstractHttpSessionApplicationInitializer { + @Autowired - Environment properties; - + private Environment properties; + @Bean @Primary - public JedisConnectionFactory connectionFactory() { - JedisConnectionFactory factory = new JedisConnectionFactory(); - factory.setHostName(properties.getProperty("spring.redis.host","localhost")); - factory.setPort(properties.getProperty("spring.redis.port", Integer.TYPE,6379)); - factory.afterPropertiesSet(); - factory.setUsePool(true); - return factory; + public LettuceConnectionFactory redisConnectionFactory() { + RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration(); + redisConfiguration.setHostName(properties.getProperty("spring.redis.host", "localhost")); + redisConfiguration.setPort(properties.getProperty("spring.redis.port", Integer.TYPE, 6379)); + return new LettuceConnectionFactory(redisConfiguration); } } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingCacheRepository.java b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingCacheRepository.java index d9f3a3584e..1263093b80 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingCacheRepository.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingCacheRepository.java @@ -6,21 +6,21 @@ import java.util.stream.Collectors; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.SetOperations; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Repository; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.stereotype.Repository; @Repository public class RatingCacheRepository implements InitializingBean { @Autowired - private JedisConnectionFactory cacheConnectionFactory; + private LettuceConnectionFactory cacheConnectionFactory; private StringRedisTemplate redisTemplate; private ValueOperations valueOps; diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java index 395ff50bd7..e02803bff3 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java @@ -2,7 +2,6 @@ package com.baeldung.spring.cloud.bootstrap.svcrating.rating; import java.util.List; import java.util.Map; -import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -10,7 +9,8 @@ import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.google.common.base.Preconditions; -import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; + +import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker; @Service @Transactional(readOnly = true) @@ -22,31 +22,31 @@ public class RatingService { @Autowired private RatingCacheRepository cacheRepository; - @HystrixCommand(commandKey = "ratingsByBookIdFromDB", fallbackMethod = "findCachedRatingsByBookId") + @CircuitBreaker(name = "ratingsByBookIdFromDB", fallbackMethod = "findCachedRatingsByBookId") public List findRatingsByBookId(Long bookId) { return ratingRepository.findRatingsByBookId(bookId); } - public List findCachedRatingsByBookId(Long bookId) { + public List findCachedRatingsByBookId(Long bookId, Exception exception) { return cacheRepository.findCachedRatingsByBookId(bookId); } - @HystrixCommand(commandKey = "ratingsFromDB", fallbackMethod = "findAllCachedRatings") + @CircuitBreaker(name = "ratingsFromDB", fallbackMethod = "findAllCachedRatings") public List findAllRatings() { return ratingRepository.findAll(); } - public List findAllCachedRatings() { + public List findAllCachedRatings(Exception exception) { return cacheRepository.findAllCachedRatings(); } - @HystrixCommand(commandKey = "ratingsByIdFromDB", fallbackMethod = "findCachedRatingById", ignoreExceptions = { RatingNotFoundException.class }) + @CircuitBreaker(name = "ratingsByIdFromDB", fallbackMethod = "findCachedRatingById") public Rating findRatingById(Long ratingId) { - return Optional.ofNullable(ratingRepository.findOne(ratingId)) + return ratingRepository.findById(ratingId) .orElseThrow(() -> new RatingNotFoundException("Rating not found. ID: " + ratingId)); } - public Rating findCachedRatingById(Long ratingId) { + public Rating findCachedRatingById(Long ratingId, Exception exception) { return cacheRepository.findCachedRatingById(ratingId); } @@ -62,7 +62,7 @@ public class RatingService { @Transactional(propagation = Propagation.REQUIRED) public void deleteRating(Long ratingId) { - ratingRepository.delete(ratingId); + ratingRepository.deleteById(ratingId); cacheRepository.deleteRating(ratingId); } @@ -86,7 +86,7 @@ public class RatingService { public Rating updateRating(Rating rating, Long ratingId) { Preconditions.checkNotNull(rating); Preconditions.checkState(rating.getId() == ratingId); - Preconditions.checkNotNull(ratingRepository.findOne(ratingId)); + Preconditions.checkNotNull(ratingRepository.findById(ratingId)); return ratingRepository.save(rating); } diff --git a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/resources/bootstrap.properties b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/resources/bootstrap.properties index be5cf7f1e1..846bc4c7aa 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/resources/bootstrap.properties +++ b/spring-cloud-modules/spring-cloud-bootstrap/svc-rating/src/main/resources/bootstrap.properties @@ -3,5 +3,7 @@ spring.cloud.config.discovery.service-id=config spring.cloud.config.discovery.enabled=true spring.cloud.config.username=configUser spring.cloud.config.password=configPassword +spring.cloud.gateway.discovery.locator.enabled=true +spring.cloud.gateway.discovery.locator.lowerCaseServiceId=true eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/ diff --git a/spring-cloud-modules/spring-cloud-bootstrap/zipkin/README.md b/spring-cloud-modules/spring-cloud-bootstrap/zipkin/README.md new file mode 100644 index 0000000000..66f150ede0 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-bootstrap/zipkin/README.md @@ -0,0 +1,19 @@ +# Zipkin server + +Zipkin project [deprecated custom server](https://github.com/openzipkin/zipkin/tree/master/zipkin-server). +It's no longer possible to run a custom Zipkin server compatible with Spring Cloud or even Spring Boot. + +The best approach to run a Zipkin server is to use docker. We provided a docker-compose file that you can run: + +```bash +$ docker compose up -d +``` + +After that Zipkin is accessible via [http://localhost:9411](http://localhost:9411) + +Alternatively, you can run the Zipkin Jar file, + +```bash +$ curl -sSL https://zipkin.io/quickstart.sh | bash -s +$ java -jar zipkin.jar +``` \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/zipkin/docker-compose.yml b/spring-cloud-modules/spring-cloud-bootstrap/zipkin/docker-compose.yml new file mode 100644 index 0000000000..20528dca8f --- /dev/null +++ b/spring-cloud-modules/spring-cloud-bootstrap/zipkin/docker-compose.yml @@ -0,0 +1,6 @@ +version: "3.9" +services: + zipkin: + image: openzipkin/zipkin + ports: + - 9411:9411 \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/zipkin/pom.xml b/spring-cloud-modules/spring-cloud-bootstrap/zipkin/pom.xml deleted file mode 100644 index b515661a00..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/zipkin/pom.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - 4.0.0 - zipkin - 1.0.0-SNAPSHOT - zipkin - - - com.baeldung - parent-boot-1 - 0.0.1-SNAPSHOT - ../../../parent-boot-1 - - - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud-dependencies.version} - pom - import - - - - - - - org.springframework.cloud - spring-cloud-starter-config - - - org.springframework.cloud - spring-cloud-starter-eureka - - - io.zipkin.java - zipkin-server - - - io.zipkin.java - zipkin-autoconfigure-ui - runtime - - - - - Brixton.SR7 - - - \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java b/spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java deleted file mode 100644 index d757567156..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.spring.cloud.bootstrap.zipkin; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.netflix.eureka.EnableEurekaClient; -import zipkin.server.EnableZipkinServer; - -@SpringBootApplication -@EnableEurekaClient -@EnableZipkinServer -public class ZipkinApplication { - public static void main(String[] args) { - SpringApplication.run(ZipkinApplication.class, args); - } -} diff --git a/spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties b/spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties deleted file mode 100644 index 9569179a4f..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties +++ /dev/null @@ -1,7 +0,0 @@ -spring.cloud.config.name=zipkin -spring.cloud.config.discovery.service-id=config -spring.cloud.config.discovery.enabled=true -spring.cloud.config.username=configUser -spring.cloud.config.password=configPassword - -eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/ \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/main/resources/logback.xml b/spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/main/resources/logback.xml deleted file mode 100644 index 7d900d8ea8..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/main/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/test/java/com/baeldung/SpringContextTest.java b/spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/test/java/com/baeldung/SpringContextTest.java deleted file mode 100644 index 71e67df191..0000000000 --- a/spring-cloud-modules/spring-cloud-bootstrap/zipkin/src/test/java/com/baeldung/SpringContextTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -import com.baeldung.spring.cloud.bootstrap.zipkin.ZipkinApplication; - -@RunWith(SpringRunner.class) -@SpringBootTest(classes = ZipkinApplication.class) -public class SpringContextTest { - - @Test - public void whenSpringContextIsBootstrapped_thenNoExceptions() { - } -} From fe1f22467226873ebf3a95cbae204c5a7e3581d7 Mon Sep 17 00:00:00 2001 From: Bipin kumar Date: Wed, 31 May 2023 19:58:13 +0530 Subject: [PATCH 15/40] =?UTF-8?q?JAVA-21305:=20Changes=20made=20for=20remo?= =?UTF-8?q?ving=20exception=20execController=20not=20sp=E2=80=A6=20(#14122?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * JAVA-21305: Chnages made for removing excpetion execController not specified causing serverstart fail * JAVA-21305: Chnages made for removing excpetion execController not specified causing serverstart fail --------- Co-authored-by: Bipin Kumar --- .../ratpack/src/main/java/com/baeldung/Application.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web-modules/ratpack/src/main/java/com/baeldung/Application.java b/web-modules/ratpack/src/main/java/com/baeldung/Application.java index 235a6f0068..8035a1d0e3 100644 --- a/web-modules/ratpack/src/main/java/com/baeldung/Application.java +++ b/web-modules/ratpack/src/main/java/com/baeldung/Application.java @@ -8,6 +8,7 @@ import com.baeldung.repository.EmployeeRepository; import com.baeldung.repository.EmployeeRepositoryImpl; import com.zaxxer.hikari.HikariConfig; import io.netty.buffer.PooledByteBufAllocator; +import ratpack.exec.internal.DefaultExecController; import ratpack.func.Action; import ratpack.func.Function; import ratpack.guice.BindingsSpec; @@ -42,7 +43,7 @@ public class Application { .maxContentLength(ServerConfig.DEFAULT_MAX_CONTENT_LENGTH) .responseMaxChunkSize(16384) .readTimeout(Duration.of(60, ChronoUnit.SECONDS)) - .byteBufAllocator(PooledByteBufAllocator.DEFAULT); + .byteBufAllocator(PooledByteBufAllocator.DEFAULT).execController(new DefaultExecController(2)); }); final Function registryFunction = Guice.registry(bindingsSpecAction); From 5917144a289532da1412c95205b846ad09137158 Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Wed, 31 May 2023 17:34:02 +0300 Subject: [PATCH 16/40] [JAVA-21545] Clean up (#14126) * [JAVA-21545] Clean up * [JAVA-21545] Clean up * [JAVA-21545] Revert change * [JAVA-21545] Clean up * [JAVA-21545] Clean up * [JAVA-21545] Clean up --- libraries-3/pom.xml | 7 ------- lombok-modules/lombok/pom.xml | 6 ------ .../spring-data-dynamodb/pom.xml | 12 +----------- spring-ejb-modules/pom.xml | 17 ----------------- 4 files changed, 1 insertion(+), 41 deletions(-) diff --git a/libraries-3/pom.xml b/libraries-3/pom.xml index 5e06a5550e..8d45b95a7b 100644 --- a/libraries-3/pom.xml +++ b/libraries-3/pom.xml @@ -129,13 +129,6 @@ - - - jitpack.io - https://jitpack.io - - - libraries-3 diff --git a/lombok-modules/lombok/pom.xml b/lombok-modules/lombok/pom.xml index 57b2a5a999..6ba90f33b5 100644 --- a/lombok-modules/lombok/pom.xml +++ b/lombok-modules/lombok/pom.xml @@ -49,10 +49,4 @@ 23.0.0 - - - projectlombok.org - https://projectlombok.org/edge-releases - - \ No newline at end of file diff --git a/persistence-modules/spring-data-dynamodb/pom.xml b/persistence-modules/spring-data-dynamodb/pom.xml index 0e990c69f3..06425cceb7 100644 --- a/persistence-modules/spring-data-dynamodb/pom.xml +++ b/persistence-modules/spring-data-dynamodb/pom.xml @@ -169,14 +169,6 @@ - - - dynamodb-local - DynamoDB Local Release Repository - ${dynamodblocal.repository.url} - - - com.baeldung.Application @@ -186,9 +178,7 @@ 1.11.64 3.3.7-1 1.0.392 - 1.11.106 - 1.11.86 - https://s3-us-west-2.amazonaws.com/dynamodb-local/release + 1.21.1 3.1.1 2.4.7 2.17.1 diff --git a/spring-ejb-modules/pom.xml b/spring-ejb-modules/pom.xml index 146d64c298..1ebfb66c32 100755 --- a/spring-ejb-modules/pom.xml +++ b/spring-ejb-modules/pom.xml @@ -55,23 +55,6 @@ - - - jboss-public-repository-group - JBoss Public Maven Repository Group - http://repository.jboss.org/nexus/content/groups/public/ - default - - true - never - - - true - never - - - - From dda5540de3e1dba8ed62ea9c03badb15287c976f Mon Sep 17 00:00:00 2001 From: Bipin kumar Date: Wed, 31 May 2023 20:15:57 +0530 Subject: [PATCH 17/40] JAVA-21106:Changes made for removing jee-7 module from jdk-9 above profile (#14157) --- pom.xml | 2 ++ web-modules/pom.xml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9cd8f4722f..8c7c5a2df7 100644 --- a/pom.xml +++ b/pom.xml @@ -366,6 +366,7 @@ muleesb web-modules/java-lite web-modules/restx + web-modules/jee-7 persistence-modules/deltaspike persistence-modules/hibernate-ogm persistence-modules/java-cassandra @@ -547,6 +548,7 @@ muleesb web-modules/java-lite web-modules/restx + web-modules/jee-7 persistence-modules/deltaspike persistence-modules/hibernate-ogm persistence-modules/java-cassandra diff --git a/web-modules/pom.xml b/web-modules/pom.xml index 97134ee31c..efd87ba642 100644 --- a/web-modules/pom.xml +++ b/web-modules/pom.xml @@ -23,7 +23,7 @@ javax-servlets javax-servlets-2 - jee-7 + jooby linkrest ninja From 96d9c016969d5d514a1fc9e24ce3a3bba6c4548d Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Wed, 31 May 2023 17:49:13 +0300 Subject: [PATCH 18/40] [JAVA-21185] Clean up (#14138) * [JAVA-21185] Clean up * [JAVA-21185] Clean up * [JAVA-21185] Clean up * Revert "[JAVA-21185] Clean up" This reverts commit 485b1b86a908ff047ba246d344392f531437c7af. * Revert "[JAVA-21185] Clean up" This reverts commit 13faeab4814ac44340a93ef67e0010bdc12799e1. --- .../quarkus-liquibase/deployment/pom.xml | 5 ---- .../quarkus-liquibase/runtime/pom.xml | 2 -- quarkus-modules/quarkus-funqy/pom.xml | 24 ++++++++++--------- .../quarkus-jandex/hello-app/pom.xml | 1 - .../hello-sender-maven-plugin/pom.xml | 6 ++++- quarkus-modules/quarkus-jandex/pom.xml | 1 - .../spring-project/pom.xml | 14 ++++++----- saas-modules/sentry-servlet/pom.xml | 21 ++++++++-------- .../java-ee-8-security-api/pom.xml | 1 - 9 files changed, 37 insertions(+), 38 deletions(-) diff --git a/quarkus-modules/quarkus-extension/quarkus-liquibase/deployment/pom.xml b/quarkus-modules/quarkus-extension/quarkus-liquibase/deployment/pom.xml index 9a9e4485cd..823b2f674a 100644 --- a/quarkus-modules/quarkus-extension/quarkus-liquibase/deployment/pom.xml +++ b/quarkus-modules/quarkus-extension/quarkus-liquibase/deployment/pom.xml @@ -41,7 +41,6 @@ org.apache.maven.plugins maven-compiler-plugin - ${compiler.plugin.version} @@ -55,8 +54,4 @@ - - 3.8.1 - - \ No newline at end of file diff --git a/quarkus-modules/quarkus-extension/quarkus-liquibase/runtime/pom.xml b/quarkus-modules/quarkus-extension/quarkus-liquibase/runtime/pom.xml index 6656556c4b..95916932a1 100644 --- a/quarkus-modules/quarkus-extension/quarkus-liquibase/runtime/pom.xml +++ b/quarkus-modules/quarkus-extension/quarkus-liquibase/runtime/pom.xml @@ -52,7 +52,6 @@ org.apache.maven.plugins maven-compiler-plugin - ${compiler.plugin.version} @@ -68,7 +67,6 @@ 3.8.1 - 3.8.1 3.8.1 diff --git a/quarkus-modules/quarkus-funqy/pom.xml b/quarkus-modules/quarkus-funqy/pom.xml index ae9c34e7e0..39a6151c69 100644 --- a/quarkus-modules/quarkus-funqy/pom.xml +++ b/quarkus-modules/quarkus-funqy/pom.xml @@ -6,17 +6,7 @@ com.baeldung.quarkus quarkus-funqy 1.0.0-SNAPSHOT - - 3.10.1 - false - 17 - UTF-8 - UTF-8 - quarkus-bom - io.quarkus.platform - 2.16.0.Final - 3.0.0-M7 - + com.baeldung quarkus-modules @@ -131,4 +121,16 @@ + + + 3.10.1 + false + 17 + UTF-8 + UTF-8 + quarkus-bom + io.quarkus.platform + 2.16.0.Final + 3.0.0-M7 + diff --git a/quarkus-modules/quarkus-jandex/hello-app/pom.xml b/quarkus-modules/quarkus-jandex/hello-app/pom.xml index 0255a6636b..fffa05d63e 100644 --- a/quarkus-modules/quarkus-jandex/hello-app/pom.xml +++ b/quarkus-modules/quarkus-jandex/hello-app/pom.xml @@ -76,7 +76,6 @@ maven-compiler-plugin - ${compiler-plugin.version} ${maven.compiler.parameters} diff --git a/quarkus-modules/quarkus-jandex/hello-sender-maven-plugin/pom.xml b/quarkus-modules/quarkus-jandex/hello-sender-maven-plugin/pom.xml index 215a00e479..8eb1b87707 100644 --- a/quarkus-modules/quarkus-jandex/hello-sender-maven-plugin/pom.xml +++ b/quarkus-modules/quarkus-jandex/hello-sender-maven-plugin/pom.xml @@ -29,7 +29,7 @@ org.jboss.jandex jandex-maven-plugin - 1.2.1 + ${jandex-maven-plugin.version} make-index @@ -43,4 +43,8 @@ + + 1.2.1 + + \ No newline at end of file diff --git a/quarkus-modules/quarkus-jandex/pom.xml b/quarkus-modules/quarkus-jandex/pom.xml index 25aeee0a46..f207854b55 100644 --- a/quarkus-modules/quarkus-jandex/pom.xml +++ b/quarkus-modules/quarkus-jandex/pom.xml @@ -38,7 +38,6 @@ - 3.8.1 true 11 11 diff --git a/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml b/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml index 13508d7086..df3eca8a4f 100644 --- a/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml +++ b/quarkus-modules/quarkus-vs-springboot/spring-project/pom.xml @@ -3,7 +3,6 @@ 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-project 0.1-SNAPSHOT @@ -19,7 +18,7 @@ org.testcontainers testcontainers-bom - 1.17.2 + ${testcontainers-bom.version} pom import @@ -43,7 +42,7 @@ com.github.jasync-sql jasync-r2dbc-mysql - 2.0.8 + ${jasync-r2dbc-mysql.version} org.springframework.boot @@ -104,7 +103,6 @@ org.apache.maven.plugins maven-compiler-plugin - ${maven-compiler-plugin.version} ${maven.compiler.source.version} ${maven.compiler.target.version} @@ -182,7 +180,7 @@ local-native exec - 0.9.11 + ${native-buildtools.version} @@ -241,7 +239,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M6 + ${maven-surefire-plugin.version} -DspringAot=true -agentlib:native-image-agent=access-filter-file=src/test/resources/access-filter.json,config-merge-dir=target/classes/META-INF/native-image @@ -254,11 +252,15 @@ + 1.17.2 11 0.12.1 3.10.1 11 11 + 3.1.0 + 0.9.11 + 2.0.8 \ No newline at end of file diff --git a/saas-modules/sentry-servlet/pom.xml b/saas-modules/sentry-servlet/pom.xml index 11dd2ad0ff..4f9e37ebd5 100644 --- a/saas-modules/sentry-servlet/pom.xml +++ b/saas-modules/sentry-servlet/pom.xml @@ -3,20 +3,15 @@ xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + sentry-servlet + sentry-servlet + war + com.baeldung saas-modules 1.0.0-SNAPSHOT - sentry-servlet - sentry-servlet - war - - - 6.11.0 - 1.10.4 - 3.3.2 - @@ -37,7 +32,7 @@ org.codehaus.cargo cargo-maven3-plugin - ${cargo.version} + ${cargo-maven3-plugin.version} tomcat9x @@ -47,4 +42,10 @@ + + + 6.11.0 + 1.10.4 + 3.3.2 + \ No newline at end of file diff --git a/security-modules/java-ee-8-security-api/pom.xml b/security-modules/java-ee-8-security-api/pom.xml index bcd15ed685..7d1a19cb88 100644 --- a/security-modules/java-ee-8-security-api/pom.xml +++ b/security-modules/java-ee-8-security-api/pom.xml @@ -34,7 +34,6 @@ maven-war-plugin - ${maven-war-plugin.version} false pom.xml From 26fe19be07ba1cd23428ec25cc26a6d44531a4c5 Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Wed, 31 May 2023 19:19:42 +0300 Subject: [PATCH 19/40] JAVA-20837 (#14140) * [JAVA-20837]Upgraded optaplanner version * upgraded dependencies --- optaplanner/pom.xml | 2 +- patterns-modules/design-patterns-architectural/pom.xml | 4 ++-- patterns-modules/design-patterns-cloud/pom.xml | 7 ++++++- .../baeldung/backoff/jitter/BackoffWithJitterUnitTest.java | 6 +++--- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/optaplanner/pom.xml b/optaplanner/pom.xml index e1653fd749..033e3a3718 100644 --- a/optaplanner/pom.xml +++ b/optaplanner/pom.xml @@ -27,7 +27,7 @@ - 8.24.0.Final + 9.38.0.Final \ No newline at end of file diff --git a/patterns-modules/design-patterns-architectural/pom.xml b/patterns-modules/design-patterns-architectural/pom.xml index 2d6117a406..4efcca0c6b 100644 --- a/patterns-modules/design-patterns-architectural/pom.xml +++ b/patterns-modules/design-patterns-architectural/pom.xml @@ -67,10 +67,10 @@ 5.2.16.Final 6.0.6 2.7.5 - 3.3.0 + 5.3.0 2.7.5 5.5.14 - 3.14.0 + 3.20.4 3.14.0 diff --git a/patterns-modules/design-patterns-cloud/pom.xml b/patterns-modules/design-patterns-cloud/pom.xml index acd3e64ed5..595e0cabcd 100644 --- a/patterns-modules/design-patterns-cloud/pom.xml +++ b/patterns-modules/design-patterns-cloud/pom.xml @@ -17,8 +17,13 @@ io.github.resilience4j resilience4j-retry - 1.7.1 + ${resilience4j-retry.version} + + + 2.0.2 + + \ No newline at end of file diff --git a/patterns-modules/design-patterns-cloud/src/test/java/com/baeldung/backoff/jitter/BackoffWithJitterUnitTest.java b/patterns-modules/design-patterns-cloud/src/test/java/com/baeldung/backoff/jitter/BackoffWithJitterUnitTest.java index abfcc71e66..5bd6b0fa23 100644 --- a/patterns-modules/design-patterns-cloud/src/test/java/com/baeldung/backoff/jitter/BackoffWithJitterUnitTest.java +++ b/patterns-modules/design-patterns-cloud/src/test/java/com/baeldung/backoff/jitter/BackoffWithJitterUnitTest.java @@ -1,6 +1,6 @@ package com.baeldung.backoff.jitter; -import io.github.resilience4j.retry.IntervalFunction; +import io.github.resilience4j.core.IntervalFunction; import io.github.resilience4j.retry.Retry; import io.github.resilience4j.retry.RetryConfig; import org.junit.Before; @@ -15,8 +15,8 @@ import java.util.concurrent.ExecutorService; import java.util.function.Function; import static com.baeldung.backoff.jitter.BackoffWithJitterUnitTest.RetryProperties.*; -import static io.github.resilience4j.retry.IntervalFunction.ofExponentialBackoff; -import static io.github.resilience4j.retry.IntervalFunction.ofExponentialRandomBackoff; +import static io.github.resilience4j.core.IntervalFunction.ofExponentialBackoff; +import static io.github.resilience4j.core.IntervalFunction.ofExponentialRandomBackoff; import static java.util.Collections.nCopies; import static java.util.concurrent.Executors.newFixedThreadPool; import static org.mockito.ArgumentMatchers.anyString; From e9171967344b8bd5bcf16cd8dbbe7ebaa4404dfd Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Wed, 31 May 2023 19:56:25 +0300 Subject: [PATCH 20/40] [JAVA-20615] Upgraded spring-security-modules to jdk9-and-above profile (#14142) * [JAVA-20615] Upgraded spring-security-modules to jdk9-and-above profile * [JAVA-20615] test build * [JAVA-20615] test build * [JAVA-20615] Clean up --- pom.xml | 7 ++++--- spring-security-modules/pom.xml | 2 +- .../spring-security-oauth2-sso/pom.xml | 1 - .../spring-security-sso-auth-server/pom.xml | 21 +++++++++++++++++++ .../spring-security-web-mvc-custom/pom.xml | 6 ++++++ .../pom.xml | 6 ++++++ .../spring-security-web-rest-custom/pom.xml | 6 ++++++ .../spring-security-web-sockets/pom.xml | 19 ++++++++++++++++- 8 files changed, 62 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 8c7c5a2df7..40397ac6c9 100644 --- a/pom.xml +++ b/pom.xml @@ -426,7 +426,7 @@ - spring-security-modules + spring-security-modules/spring-security-ldap spring-soap spring-static-resources spring-swagger-codegen @@ -600,7 +600,7 @@ - spring-security-modules + spring-security-modules/spring-security-ldap spring-soap spring-static-resources spring-swagger-codegen @@ -915,7 +915,7 @@ spring-kafka spring-native - spring-security-modules/spring-security-oauth2-testing + spring-security-modules spring-protobuf spring-quartz @@ -1177,6 +1177,7 @@ spring-kafka spring-native + spring-security-modules spring-protobuf spring-quartz diff --git a/spring-security-modules/pom.xml b/spring-security-modules/pom.xml index 030f1ef876..2c9a8e3dfe 100644 --- a/spring-security-modules/pom.xml +++ b/spring-security-modules/pom.xml @@ -20,7 +20,7 @@ spring-security-cognito spring-security-core spring-security-core-2 - spring-security-ldap + spring-security-legacy-oidc spring-security-oauth2 spring-security-oauth2-sso diff --git a/spring-security-modules/spring-security-oauth2-sso/pom.xml b/spring-security-modules/spring-security-oauth2-sso/pom.xml index c9f9274c98..a87e4d7814 100644 --- a/spring-security-modules/spring-security-oauth2-sso/pom.xml +++ b/spring-security-modules/spring-security-oauth2-sso/pom.xml @@ -3,7 +3,6 @@ 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-security-oauth2-sso 1.0.0-SNAPSHOT spring-security-oauth2-sso diff --git a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-auth-server/pom.xml b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-auth-server/pom.xml index 1a8d1b580f..9ecea81ed3 100644 --- a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-auth-server/pom.xml +++ b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-auth-server/pom.xml @@ -23,6 +23,27 @@ spring-security-oauth2 ${oauth.version} + + jakarta.annotation + jakarta.annotation-api + ${jakarta.annotation-api.version} + + + jakarta.xml.bind + jakarta.xml.bind-api + ${jakarta.xml.bind-api.version} + + + org.glassfish.jaxb + jaxb-runtime + ${jaxb-runtime.version} + + + 1.3.5 + 2.3.3 + 2.3.5 + + \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-mvc-custom/pom.xml b/spring-security-modules/spring-security-web-mvc-custom/pom.xml index 104b7025ad..f21c6dbe40 100644 --- a/spring-security-modules/spring-security-web-mvc-custom/pom.xml +++ b/spring-security-modules/spring-security-web-mvc-custom/pom.xml @@ -126,6 +126,11 @@ ${spring-security.version} test + + javax.annotation + javax.annotation-api + ${javax.annotation-api.version} + @@ -169,6 +174,7 @@ 3.2.2 1.6.1 + 1.3.2 \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-rest-basic-auth/pom.xml b/spring-security-modules/spring-security-web-rest-basic-auth/pom.xml index 291d732049..3c842a8a54 100644 --- a/spring-security-modules/spring-security-web-rest-basic-auth/pom.xml +++ b/spring-security-modules/spring-security-web-rest-basic-auth/pom.xml @@ -127,6 +127,11 @@ spring-test test + + javax.xml.bind + jaxb-api + ${jaxb-api.version} + @@ -220,6 +225,7 @@ + 2.3.1 4.4.11 4.5.8 diff --git a/spring-security-modules/spring-security-web-rest-custom/pom.xml b/spring-security-modules/spring-security-web-rest-custom/pom.xml index d420c45df2..dfd2f59aaf 100644 --- a/spring-security-modules/spring-security-web-rest-custom/pom.xml +++ b/spring-security-modules/spring-security-web-rest-custom/pom.xml @@ -115,6 +115,11 @@ commons-lang3 ${commons-lang3.version} + + javax.xml.bind + jaxb-api + ${jaxb-api.version} + @@ -165,6 +170,7 @@ 1.2 + 2.3.1 1.6.1 diff --git a/spring-security-modules/spring-security-web-sockets/pom.xml b/spring-security-modules/spring-security-web-sockets/pom.xml index 802c894612..513ee28c85 100644 --- a/spring-security-modules/spring-security-web-sockets/pom.xml +++ b/spring-security-modules/spring-security-web-sockets/pom.xml @@ -149,6 +149,12 @@ ${spring-boot-starter-test.version} test + + + javax.xml.bind + jaxb-api + ${jaxb-api.version} + @@ -168,12 +174,22 @@ org.apache.maven.plugins maven-war-plugin - 3.0.0 + ${maven-war-plugin.version} src/main/webapp false + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.lang=ALL-UNNAMED + --add-opens java.base/java.lang.invoke=ALL-UNNAMED + + + @@ -182,6 +198,7 @@ 1.11.3.RELEASE 1.5.10.RELEASE 1.7.6 + 2.3.1 \ No newline at end of file From 6ca8c123c570ef11fbc71f0b147b526a48e2d7d9 Mon Sep 17 00:00:00 2001 From: panos-kakos <102670093+panos-kakos@users.noreply.github.com> Date: Wed, 31 May 2023 19:58:19 +0300 Subject: [PATCH 21/40] =?UTF-8?q?[JAVA-20622]=20Upgraded=20spring-web-modu?= =?UTF-8?q?les=20to=20jdk9-and-above=20profile=20+=20=E2=80=A6=20(#14154)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [JAVA-20622] Upgraded spring-web-modules to jdk9-and-above profile + minor clean up * [JAVA-20622] Fixed issue at spring-freemarker module --- pom.xml | 4 ++-- spring-web-modules/spring-freemarker/pom.xml | 16 +++++++++++++++- spring-web-modules/spring-mvc-basics-2/pom.xml | 3 --- spring-web-modules/spring-mvc-basics-5/pom.xml | 16 +++++++++++++--- spring-web-modules/spring-mvc-basics/pom.xml | 9 +++++++++ spring-web-modules/spring-mvc-crash/pom.xml | 10 +++++++++- spring-web-modules/spring-mvc-forms-jsp/pom.xml | 7 ++++++- spring-web-modules/spring-mvc-java-2/pom.xml | 6 ++++++ spring-web-modules/spring-mvc-java/pom.xml | 2 -- spring-web-modules/spring-mvc-velocity/pom.xml | 10 +++++++++- spring-web-modules/spring-mvc-views/pom.xml | 6 ------ spring-web-modules/spring-mvc-webflow/pom.xml | 13 +++++++++++-- spring-web-modules/spring-mvc-xml-2/pom.xml | 10 +++++++++- spring-web-modules/spring-mvc-xml/pom.xml | 10 +++++++++- spring-web-modules/spring-thymeleaf-4/pom.xml | 1 - 15 files changed, 98 insertions(+), 25 deletions(-) diff --git a/pom.xml b/pom.xml index 40397ac6c9..8a494719a8 100644 --- a/pom.xml +++ b/pom.xml @@ -430,7 +430,6 @@ spring-soap spring-static-resources spring-swagger-codegen - spring-web-modules testing-modules video-tutorials @@ -604,7 +603,6 @@ spring-soap spring-static-resources spring-swagger-codegen - spring-web-modules testing-modules video-tutorials @@ -927,6 +925,7 @@ spring-threads spring-vault spring-websockets + spring-web-modules static-analysis tensorflow-java vertx-modules @@ -1189,6 +1188,7 @@ spring-threads spring-vault spring-websockets + spring-web-modules static-analysis tensorflow-java vertx-modules diff --git a/spring-web-modules/spring-freemarker/pom.xml b/spring-web-modules/spring-freemarker/pom.xml index 07d37736b6..9ac01fd106 100644 --- a/spring-web-modules/spring-freemarker/pom.xml +++ b/spring-web-modules/spring-freemarker/pom.xml @@ -55,9 +55,23 @@ + + + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + 5.0.8.RELEASE - 2.3.28 + 2.3.32 false 1.5.10.RELEASE diff --git a/spring-web-modules/spring-mvc-basics-2/pom.xml b/spring-web-modules/spring-mvc-basics-2/pom.xml index 79d1531274..28eb3a16f2 100644 --- a/spring-web-modules/spring-mvc-basics-2/pom.xml +++ b/spring-web-modules/spring-mvc-basics-2/pom.xml @@ -136,7 +136,6 @@ org.apache.maven.plugins maven-war-plugin - ${maven-war-plugin.version} src/main/webapp springMvcSimple @@ -149,8 +148,6 @@ - 1.8 - 1.8 6.0.10.Final enter-location-of-server 3.0.11.RELEASE diff --git a/spring-web-modules/spring-mvc-basics-5/pom.xml b/spring-web-modules/spring-mvc-basics-5/pom.xml index 0f2b0bc7bd..c957d669bd 100644 --- a/spring-web-modules/spring-mvc-basics-5/pom.xml +++ b/spring-web-modules/spring-mvc-basics-5/pom.xml @@ -41,14 +41,18 @@ org.apache.commons commons-io - 1.3.2 + ${commons-io.version} com.jayway.jsonpath json-path - 2.7.0 + ${json-path.version} + + + org.glassfish.jaxb + jaxb-runtime + ${jaxb-runtime.version} - @@ -65,4 +69,10 @@ + + 1.3.2 + 2.7.0 + 2.3.5 + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-basics/pom.xml b/spring-web-modules/spring-mvc-basics/pom.xml index ccd6773e6f..0f1d423ca2 100644 --- a/spring-web-modules/spring-mvc-basics/pom.xml +++ b/spring-web-modules/spring-mvc-basics/pom.xml @@ -39,6 +39,11 @@ spring-boot-starter-test test + + org.glassfish.jaxb + jaxb-runtime + ${jaxb-runtime.version} + @@ -55,4 +60,8 @@ + + 2.3.5 + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-crash/pom.xml b/spring-web-modules/spring-mvc-crash/pom.xml index 2b7b79666d..f3faa18816 100644 --- a/spring-web-modules/spring-mvc-crash/pom.xml +++ b/spring-web-modules/spring-mvc-crash/pom.xml @@ -124,7 +124,15 @@ org.apache.maven.plugins maven-war-plugin - ${maven-war-plugin.version} + + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.lang=ALL-UNNAMED + + diff --git a/spring-web-modules/spring-mvc-forms-jsp/pom.xml b/spring-web-modules/spring-mvc-forms-jsp/pom.xml index b0269e3344..3ad815e95f 100644 --- a/spring-web-modules/spring-mvc-forms-jsp/pom.xml +++ b/spring-web-modules/spring-mvc-forms-jsp/pom.xml @@ -68,6 +68,11 @@ ${spring-boot-starter-test.version} test + + javax.annotation + javax.annotation-api + ${javax.annotation-api.version} + @@ -83,7 +88,6 @@ org.apache.maven.plugins maven-war-plugin - ${maven-war-plugin.version} src/main/webapp spring-mvc-forms @@ -101,6 +105,7 @@ 6.0.10.Final 5.2.5.Final 6.0.6 + 1.3.2 \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-java-2/pom.xml b/spring-web-modules/spring-mvc-java-2/pom.xml index 1bbb066786..d88a9c320a 100644 --- a/spring-web-modules/spring-mvc-java-2/pom.xml +++ b/spring-web-modules/spring-mvc-java-2/pom.xml @@ -36,6 +36,11 @@ commons-io ${commons-io.version} + + org.glassfish.jaxb + jaxb-runtime + ${jaxb-runtime.version} + @@ -51,6 +56,7 @@ 4.0.1 5.2.2.RELEASE + 2.3.5 \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-java/pom.xml b/spring-web-modules/spring-mvc-java/pom.xml index 208973eccb..8098f07282 100644 --- a/spring-web-modules/spring-mvc-java/pom.xml +++ b/spring-web-modules/spring-mvc-java/pom.xml @@ -126,7 +126,6 @@ org.apache.maven.plugins maven-war-plugin - ${maven-war-plugin.version} false @@ -227,7 +226,6 @@ 4.5.2 2.23 - 3.2.2 2.7 1.6.1 3.1.0 diff --git a/spring-web-modules/spring-mvc-velocity/pom.xml b/spring-web-modules/spring-mvc-velocity/pom.xml index 1b1e8b1ea4..676fa09dac 100644 --- a/spring-web-modules/spring-mvc-velocity/pom.xml +++ b/spring-web-modules/spring-mvc-velocity/pom.xml @@ -88,11 +88,19 @@ org.apache.maven.plugins maven-war-plugin - ${maven-war-plugin.version} false + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.lang=ALL-UNNAMED + + + diff --git a/spring-web-modules/spring-mvc-views/pom.xml b/spring-web-modules/spring-mvc-views/pom.xml index 79cf82bc0b..d2b5d45366 100644 --- a/spring-web-modules/spring-mvc-views/pom.xml +++ b/spring-web-modules/spring-mvc-views/pom.xml @@ -83,16 +83,10 @@ org.apache.maven.plugins maven-compiler-plugin - 2.0.2 - - ${java.version} - ${java.version} - org.apache.maven.plugins maven-war-plugin - ${maven-war-plugin.version} src/main/webapp spring-mvc-views diff --git a/spring-web-modules/spring-mvc-webflow/pom.xml b/spring-web-modules/spring-mvc-webflow/pom.xml index 69985a7b9d..a128103bac 100644 --- a/spring-web-modules/spring-mvc-webflow/pom.xml +++ b/spring-web-modules/spring-mvc-webflow/pom.xml @@ -71,7 +71,7 @@ org.apache.tomee.maven tomee-maven-plugin - 8.0.1 + ${tomee-maven-plugin.version} 8080 spring-mvc-webflow @@ -91,11 +91,19 @@ org.apache.maven.plugins maven-war-plugin - ${maven-war-plugin.version} false + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.lang=ALL-UNNAMED + + + @@ -110,6 +118,7 @@ 2.7 1.6.1 1.5.10.RELEASE + 8.0.1 \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-xml-2/pom.xml b/spring-web-modules/spring-mvc-xml-2/pom.xml index 5910823e95..f4326ccf68 100644 --- a/spring-web-modules/spring-mvc-xml-2/pom.xml +++ b/spring-web-modules/spring-mvc-xml-2/pom.xml @@ -81,7 +81,15 @@ org.apache.maven.plugins maven-war-plugin - ${maven-war-plugin.version} + + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.lang=ALL-UNNAMED + + diff --git a/spring-web-modules/spring-mvc-xml/pom.xml b/spring-web-modules/spring-mvc-xml/pom.xml index d8d4082219..bf0dc52b68 100644 --- a/spring-web-modules/spring-mvc-xml/pom.xml +++ b/spring-web-modules/spring-mvc-xml/pom.xml @@ -119,7 +119,15 @@ org.apache.maven.plugins maven-war-plugin - ${maven-war-plugin.version} + + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.lang=ALL-UNNAMED + + diff --git a/spring-web-modules/spring-thymeleaf-4/pom.xml b/spring-web-modules/spring-thymeleaf-4/pom.xml index 8063b14c39..163d590c9f 100644 --- a/spring-web-modules/spring-thymeleaf-4/pom.xml +++ b/spring-web-modules/spring-thymeleaf-4/pom.xml @@ -107,7 +107,6 @@ org.apache.maven.plugins maven-war-plugin - ${maven-war-plugin.version} false From b58c47df2342b40ef490ea13ddd1a811d6aa336e Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Wed, 31 May 2023 23:14:00 +0530 Subject: [PATCH 22/40] JAVA-15022 Added MockServer support for LiveTest (#14158) --- apache-httpclient/pom.xml | 7 ++ .../httpclient/GetRequestMockServer.java | 80 +++++++++++++++++++ .../httpclient/HttpAsyncClientLiveTest.java | 2 +- 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 apache-httpclient/src/test/java/com/baeldung/httpclient/GetRequestMockServer.java diff --git a/apache-httpclient/pom.xml b/apache-httpclient/pom.xml index c371d1fc06..5c3ea5b3b3 100644 --- a/apache-httpclient/pom.xml +++ b/apache-httpclient/pom.xml @@ -90,6 +90,12 @@ + + org.mock-server + mockserver-netty + ${mockserver.version} + + com.github.tomakehurst wiremock @@ -112,6 +118,7 @@ 4.1.4 + 5.6.1 2.5.1 4.5.8 diff --git a/apache-httpclient/src/test/java/com/baeldung/httpclient/GetRequestMockServer.java b/apache-httpclient/src/test/java/com/baeldung/httpclient/GetRequestMockServer.java new file mode 100644 index 0000000000..f65558906f --- /dev/null +++ b/apache-httpclient/src/test/java/com/baeldung/httpclient/GetRequestMockServer.java @@ -0,0 +1,80 @@ +package com.baeldung.httpclient; + +import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import static org.mockserver.matchers.Times.exactly; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.URISyntaxException; + +import org.apache.http.HttpStatus; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.mockserver.client.MockServerClient; +import org.mockserver.integration.ClientAndServer; + +public class GetRequestMockServer { + + public static ClientAndServer mockServer; + public static String serviceOneUrl; + public static String serviceTwoUrl; + + private static int serverPort; + + public static final String SERVER_ADDRESS = "127.0.0.1"; + public static final String PATH_ONE = "/test1"; + public static final String PATH_TWO = "/test2"; + public static final String METHOD = "GET"; + + @BeforeAll + static void startServer() throws IOException, URISyntaxException { + //serverPort = getFreePort(); + serverPort = 8080; + System.out.println("Free port "+serverPort); + serviceOneUrl = "http://" + SERVER_ADDRESS + ":" + serverPort + PATH_ONE; + serviceTwoUrl = "http://" + SERVER_ADDRESS + ":" + serverPort + PATH_TWO; + mockServer = startClientAndServer(serverPort); + mockGetRequest(); + } + + @AfterAll + static void stopServer() { + mockServer.stop(); + } + + private static void mockGetRequest() { + new MockServerClient(SERVER_ADDRESS, serverPort) + .when( + request() + .withPath(PATH_ONE) + .withMethod(METHOD), + exactly(5) + ) + .respond( + response() + .withStatusCode(HttpStatus.SC_OK) + .withBody("{\"status\":\"ok\"}") + ); + new MockServerClient(SERVER_ADDRESS, serverPort) + .when( + request() + .withPath(PATH_TWO) + .withMethod(METHOD), + exactly(1) + ) + .respond( + response() + .withStatusCode(HttpStatus.SC_OK) + .withBody("{\"status\":\"ok\"}") + ); + } + + private static int getFreePort () throws IOException { + try (ServerSocket serverSocket = new ServerSocket(0)) { + return serverSocket.getLocalPort(); + } + } + +} diff --git a/apache-httpclient/src/test/java/com/baeldung/httpclient/HttpAsyncClientLiveTest.java b/apache-httpclient/src/test/java/com/baeldung/httpclient/HttpAsyncClientLiveTest.java index ab0e4e6308..f4b9266d7e 100644 --- a/apache-httpclient/src/test/java/com/baeldung/httpclient/HttpAsyncClientLiveTest.java +++ b/apache-httpclient/src/test/java/com/baeldung/httpclient/HttpAsyncClientLiveTest.java @@ -38,7 +38,7 @@ import org.apache.hc.core5.ssl.SSLContexts; import org.apache.hc.core5.ssl.TrustStrategy; -class HttpAsyncClientLiveTest { +class HttpAsyncClientLiveTest extends GetRequestMockServer { private static final String HOST = "http://www.google.com"; private static final String HOST_WITH_SSL = "https://mms.nw.ru/"; From 02f497bf751fd154618abd75e5cf4942b6c28cee Mon Sep 17 00:00:00 2001 From: Bahaa El-Din Helmy Date: Wed, 31 May 2023 21:09:25 +0300 Subject: [PATCH 23/40] Update article "Difference Between \z and \Z in a Regular Expression in Java" (#14151) This commit for "Update article "Difference Between \z and \Z in a Regular Expression in Java"" --- .../z_regexp/ZRegularExpressionUnitTest.java | 62 ++++++++++++++++--- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/core-java-modules/core-java-regex-2/src/test/java/com/baeldung/regex/z_regexp/ZRegularExpressionUnitTest.java b/core-java-modules/core-java-regex-2/src/test/java/com/baeldung/regex/z_regexp/ZRegularExpressionUnitTest.java index 90bbbb6540..a24682fc1a 100644 --- a/core-java-modules/core-java-regex-2/src/test/java/com/baeldung/regex/z_regexp/ZRegularExpressionUnitTest.java +++ b/core-java-modules/core-java-regex-2/src/test/java/com/baeldung/regex/z_regexp/ZRegularExpressionUnitTest.java @@ -3,33 +3,81 @@ package com.baeldung.regex.z_regexp; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.regex.Pattern; public class ZRegularExpressionUnitTest { @Test public void givenCreditCardNumber_thenReturnIfMatched() { String creditCardNumber = "1234567890123456"; + String creditCardNumber2 = "1234567890123456\n"; String pattern = "\\d{16}\\z"; - Assertions.assertTrue(creditCardNumber.matches(pattern)); + Assertions.assertTrue(Pattern.compile(pattern).matcher(creditCardNumber).find()); + Assertions.assertFalse(Pattern.compile(pattern).matcher(creditCardNumber2).find()); + } + + @Test + public void givenCreditCardNumber_thenReturnIfNotMatched() { + String creditCardNumber = "1234567890123456\n"; + String pattern = "\\d{16}\\z"; + Assertions.assertFalse(Pattern.compile(pattern).matcher(creditCardNumber).find()); } @Test public void givenLogOutput_thenReturnIfMatched() { String logLine = "2022-05-01 14:30:00,123 INFO Some log message"; String pattern = ".*message\\z"; - Assertions.assertTrue(logLine.matches(pattern)); + Assertions.assertTrue(Pattern.compile(pattern).matcher(logLine).find()); } + @Test + public void givenLogOutput_thenReturnIfNotMatched() { + String logLine = "2022-05-01 14:30:00,123 INFO Some log message\n"; + String pattern = ".*message\\z"; + Assertions.assertFalse(Pattern.compile(pattern).matcher(logLine).find()); + } @Test public void givenEmailMessage_thenReturnIfMatched() { String myMessage = "Hello HR, I hope i can write to Baeldung\n"; - String pattern = ".*Baeldung\\s*\\Z"; - Assertions.assertTrue(myMessage.matches(pattern)); + String myMessage2 = "Hello HR, I hope\n i can write to Baeldung"; + String pattern = ".*Baeldung\\Z"; + String pattern2 = ".*hope\\Z"; + Assertions.assertTrue(Pattern.compile(pattern).matcher(myMessage).find()); + Assertions.assertFalse(Pattern.compile(pattern2).matcher(myMessage2).find()); + } + + @Test + public void givenEmailMessage_thenReturnIfNotMatched() { + String myMessage = "Hello HR, I hope\n i can write to Baeldung"; + String pattern = ".*hope\\Z"; + Assertions.assertFalse(Pattern.compile(pattern).matcher(myMessage).find()); } @Test public void givenFileExtension_thenReturnIfMatched() { - String fileName = "image.jpeg"; + String fileName = "image.jpeg\n"; + String fileName2 = "image2.jpeg\n.png"; String pattern = ".*\\.jpeg\\Z"; - Assertions.assertTrue(fileName.matches(pattern)); + Assertions.assertTrue(Pattern.compile(pattern).matcher(fileName).find()); + Assertions.assertFalse(Pattern.compile(pattern).matcher(fileName2).find()); } -} + @Test + public void givenFileExtension_thenReturnIfNotMatched() { + String fileName = "image2.jpeg\n.png"; + String pattern = ".*\\.jpeg\\Z"; + Assertions.assertFalse(Pattern.compile(pattern).matcher(fileName).find()); + } + @Test + public void givenURL_thenReturnIfMatched() { + String url = "https://www.example.com/api/endpoint\n"; + String pattern = ".*/endpoint$"; + Assertions.assertTrue(Pattern.compile(pattern).matcher(url).find()); + } + + @Test + public void givenSentence_thenReturnIfMatched() { + String sentence = "Hello, how are you?"; + String pattern = ".*[.?!]$"; + Assertions.assertTrue(Pattern.compile(pattern).matcher(sentence).find()); + } + +} \ No newline at end of file From 09381943007483d5b8dc148d5e7d31af2c5e01bc Mon Sep 17 00:00:00 2001 From: Bahaa El-Din Helmy Date: Wed, 31 May 2023 21:35:56 +0300 Subject: [PATCH 24/40] Article: Converting Object To Map in Java (#14160) This commit is related to the article entitled "Converting Object To Map in Java" --- .../objecttomap/ObjectToMapUnitTest.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 core-java-modules/core-java-collections-maps-6/src/test/com/baeldung/objecttomap/ObjectToMapUnitTest.java diff --git a/core-java-modules/core-java-collections-maps-6/src/test/com/baeldung/objecttomap/ObjectToMapUnitTest.java b/core-java-modules/core-java-collections-maps-6/src/test/com/baeldung/objecttomap/ObjectToMapUnitTest.java new file mode 100644 index 0000000000..52c2fb2bea --- /dev/null +++ b/core-java-modules/core-java-collections-maps-6/src/test/com/baeldung/objecttomap/ObjectToMapUnitTest.java @@ -0,0 +1,76 @@ +package java.com.baeldung.objecttomap; +import com.google.gson.Gson; +import org.junit.Assert; +import org.junit.Test; +import wiremock.com.fasterxml.jackson.core.type.TypeReference; +import wiremock.com.fasterxml.jackson.databind.ObjectMapper; +import wiremock.com.google.common.reflect.TypeToken; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +public class ObjectToMapUnitTest { + Employee employee = new Employee("John", 3000.0); + + @Test + public void givenJavaObject_whenUsingReflection_thenConvertToMap() throws IllegalAccessException { + Map map = convertUsingReflection(employee); + Assert.assertEquals(employee.getName(), map.get("name")); + Assert.assertEquals(employee.getSalary(), map.get("salary")); + } + + private Map convertUsingReflection(Object object) throws IllegalAccessException { + Map map = new HashMap<>(); + Field[] fields = object.getClass().getDeclaredFields(); + + for (Field field : fields) { + field.setAccessible(true); + map.put(field.getName(), field.get(object)); + } + + return map; + } + + @Test + public void givenJavaObject_whenUsingJackson_thenConvertToMap() { + ObjectMapper objectMapper = new ObjectMapper(); + Map map = objectMapper.convertValue(employee, new TypeReference>() {}); + Assert.assertEquals(employee.getName(), map.get("name")); + Assert.assertEquals(employee.getSalary(), map.get("salary")); + } + + @Test + public void givenJavaObject_whenUsingGson_thenConvertToMap() { + Gson gson = new Gson(); + String json = gson.toJson(employee); + Map map = gson.fromJson(json, new TypeToken>() {}.getType()); + Assert.assertEquals(employee.getName(), map.get("name")); + Assert.assertEquals(employee.getSalary(), map.get("salary")); + } + + private static class Employee { + private String name; + private Double salary; + + public Employee(String name, Double salary) { + this.name = name; + this.salary = salary; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Double getSalary() { + return salary; + } + + public void setSalary(Double age) { + this.salary = salary; + } + } +} From dfa2ef7a8e66d29ef4448385aaf4eefd7c942ae4 Mon Sep 17 00:00:00 2001 From: Pedro Lopes Date: Wed, 31 May 2023 16:32:16 -0300 Subject: [PATCH 25/40] BAEL 6249: Gray Box Testing (#13610) * test implementation and sut class * finishing up unit tests * format * fix test name * changing method source name * creating new module testing-techniques * fix package name --------- Co-authored-by: Ashley Frieze --- testing-modules/pom.xml | 1 + testing-modules/testing-techniques/pom.xml | 14 ++++ .../SalaryCommissionPercentageCalculator.java | 67 +++++++++++++++++++ ...ommissionPercentageCalculatorUnitTest.java | 41 ++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 testing-modules/testing-techniques/pom.xml create mode 100644 testing-modules/testing-techniques/src/main/java/com/baeldung/greyboxtesting/SalaryCommissionPercentageCalculator.java create mode 100644 testing-modules/testing-techniques/src/test/java/com/baeldung/greyboxtesting/SalaryCommissionPercentageCalculatorUnitTest.java diff --git a/testing-modules/pom.xml b/testing-modules/pom.xml index a6b5fba570..9080d5a0ea 100644 --- a/testing-modules/pom.xml +++ b/testing-modules/pom.xml @@ -52,6 +52,7 @@ xmlunit-2 zerocode mockito-2 + testing-techniques gatling-java diff --git a/testing-modules/testing-techniques/pom.xml b/testing-modules/testing-techniques/pom.xml new file mode 100644 index 0000000000..5902047aeb --- /dev/null +++ b/testing-modules/testing-techniques/pom.xml @@ -0,0 +1,14 @@ + + + + testing-techniques + 4.0.0 + + + testing-modules + com.baeldung + 1.0.0-SNAPSHOT + + \ No newline at end of file diff --git a/testing-modules/testing-techniques/src/main/java/com/baeldung/greyboxtesting/SalaryCommissionPercentageCalculator.java b/testing-modules/testing-techniques/src/main/java/com/baeldung/greyboxtesting/SalaryCommissionPercentageCalculator.java new file mode 100644 index 0000000000..d97b6687b3 --- /dev/null +++ b/testing-modules/testing-techniques/src/main/java/com/baeldung/greyboxtesting/SalaryCommissionPercentageCalculator.java @@ -0,0 +1,67 @@ +package com.baeldung.greyboxtesting; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.stream.DoubleStream; + +public class SalaryCommissionPercentageCalculator { + public BigDecimal calculate(Level level, Type type, Seniority seniority, SalesImpact impact) { + return BigDecimal.valueOf(DoubleStream.of(level.getBonus(), type.getBonus(), seniority.getBonus(), impact.getBonus(), type.getBonus()) + .average() + .orElse(0)) + .setScale(2, RoundingMode.CEILING); + } + + public enum Level { + L1(0.06), L2(0.12), L3(0.2); + private double bonus; + + Level(double bonus) { + this.bonus = bonus; + } + + public double getBonus() { + return bonus; + } + } + + public enum Type { + FULL_TIME_COMMISSIONED(0.18), CONTRACTOR(0.1), FREELANCER(0.06); + + private double bonus; + + Type(double bonus) { + this.bonus = bonus; + } + + public double getBonus() { + return bonus; + } + } + + public enum Seniority { + JR(0.8), MID(0.13), SR(0.19); + private double bonus; + + Seniority(double bonus) { + this.bonus = bonus; + } + + public double getBonus() { + return bonus; + } + } + + public enum SalesImpact { + LOW(0.06), MEDIUM(0.12), HIGH(0.2); + private double bonus; + + SalesImpact(double bonus) { + this.bonus = bonus; + } + + public double getBonus() { + return bonus; + } + } +} diff --git a/testing-modules/testing-techniques/src/test/java/com/baeldung/greyboxtesting/SalaryCommissionPercentageCalculatorUnitTest.java b/testing-modules/testing-techniques/src/test/java/com/baeldung/greyboxtesting/SalaryCommissionPercentageCalculatorUnitTest.java new file mode 100644 index 0000000000..e39a1e5445 --- /dev/null +++ b/testing-modules/testing-techniques/src/test/java/com/baeldung/greyboxtesting/SalaryCommissionPercentageCalculatorUnitTest.java @@ -0,0 +1,41 @@ +package com.baeldung.greyboxtesting; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.math.BigDecimal; +import java.util.stream.Stream; + +import static com.baeldung.greyboxtesting.SalaryCommissionPercentageCalculator.*; +import static com.baeldung.greyboxtesting.SalaryCommissionPercentageCalculator.Level.*; +import static com.baeldung.greyboxtesting.SalaryCommissionPercentageCalculator.SalesImpact.*; +import static com.baeldung.greyboxtesting.SalaryCommissionPercentageCalculator.Seniority.*; +import static com.baeldung.greyboxtesting.SalaryCommissionPercentageCalculator.Type.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class SalaryCommissionPercentageCalculatorUnitTest { + + private SalaryCommissionPercentageCalculator testTarget = new SalaryCommissionPercentageCalculator(); + + @ParameterizedTest + @MethodSource("provideReferenceTestScenarioTable") + void givenReferenceTable_whenCalculateAverageCommission_thenReturnExpectedResult(Level level, Type type, Seniority seniority, SalesImpact impact, double expected) { + BigDecimal got = testTarget.calculate(level, type, seniority, impact); + assertEquals(BigDecimal.valueOf(expected), got); + } + + private static Stream provideReferenceTestScenarioTable() { + return Stream.of( + Arguments.of(L1, FULL_TIME_COMMISSIONED, JR, LOW, 0.26), + Arguments.of(L1, CONTRACTOR, SR, MEDIUM, 0.12), + Arguments.of(L1, FREELANCER, MID, HIGH, 0.11), + Arguments.of(L2, FULL_TIME_COMMISSIONED, SR, HIGH, 0.18), + Arguments.of(L2, CONTRACTOR, MID, LOW, 0.11), + Arguments.of(L2, FREELANCER, JR, MEDIUM, 0.24), + Arguments.of(L3, FULL_TIME_COMMISSIONED, MID, MEDIUM, 0.17), + Arguments.of(L3, CONTRACTOR, JR, HIGH, 0.28), + Arguments.of(L3, FREELANCER, SR, LOW, 0.12) + ); + } +} \ No newline at end of file From 5c7212c3d07cb579d0029a557333b6b08e364fec Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:10:17 +0800 Subject: [PATCH 26/40] Update README.md [skip ci] --- json-modules/gson-2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json-modules/gson-2/README.md b/json-modules/gson-2/README.md index 40d5515567..5580479753 100644 --- a/json-modules/gson-2/README.md +++ b/json-modules/gson-2/README.md @@ -3,5 +3,5 @@ This module contains articles about Gson ### Relevant Articles: - +- [Solving Gson Parsing Errors](https://www.baeldung.com/gson-parsing-errors) From 857442f347a9571da3ea29c19f7bb7fb7ae34199 Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:13:40 +0800 Subject: [PATCH 27/40] Update README.md [skip ci] --- core-java-modules/core-java-io-apis-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-io-apis-2/README.md b/core-java-modules/core-java-io-apis-2/README.md index 9bd55abac4..7f04d6d028 100644 --- a/core-java-modules/core-java-io-apis-2/README.md +++ b/core-java-modules/core-java-io-apis-2/README.md @@ -12,3 +12,4 @@ This module contains articles about core Java input/output(IO) APIs. - [Storing Java Scanner Input in an Array](https://www.baeldung.com/java-store-scanner-input-in-array) - [How to Take Input as String With Spaces in Java Using Scanner?](https://www.baeldung.com/java-scanner-input-with-spaces) - [Write Console Output to Text File in Java](https://www.baeldung.com/java-write-console-output-file) +- [What’s the difference between Scanner next() and nextLine() methods?](https://www.baeldung.com/java-scanner-next-vs-nextline) From 8ca4e21db4c8229eaa8d1739bc3ab0fa2b542e06 Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:16:39 +0800 Subject: [PATCH 28/40] Update README.md [skip ci] --- core-java-modules/core-java-collections-list-5/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-collections-list-5/README.md b/core-java-modules/core-java-collections-list-5/README.md index 31688bc9b1..5c88f821f8 100644 --- a/core-java-modules/core-java-collections-list-5/README.md +++ b/core-java-modules/core-java-collections-list-5/README.md @@ -7,3 +7,4 @@ This module contains articles about the Java List collection - [Finding All Duplicates in a List in Java](https://www.baeldung.com/java-list-find-duplicates) - [Moving Items Around in an Arraylist](https://www.baeldung.com/java-arraylist-move-items) - [Check if a List Contains an Element From Another List in Java](https://www.baeldung.com/java-check-elements-between-lists) +- [Array vs. List Performance in Java](https://www.baeldung.com/java-array-vs-list-performance) From 4a2d613531da7ee54c9fe1954bec36f3ebdda35c Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:24:42 +0800 Subject: [PATCH 29/40] Update README.md [skip ci] --- spring-security-modules/spring-security-web-boot-4/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-modules/spring-security-web-boot-4/README.md b/spring-security-modules/spring-security-web-boot-4/README.md index af8ed4e76a..8a7dbf3029 100644 --- a/spring-security-modules/spring-security-web-boot-4/README.md +++ b/spring-security-modules/spring-security-web-boot-4/README.md @@ -9,5 +9,5 @@ The "REST With Spring" Classes: http://github.learnspringsecurity.com - [Spring Security: Upgrading the Deprecated WebSecurityConfigurerAdapter](https://www.baeldung.com/spring-deprecated-websecurityconfigureradapter) - [Spring @EnableMethodSecurity Annotation](https://www.baeldung.com/spring-enablemethodsecurity) - +- [Securing Spring Boot API With API Key and Secret](https://www.baeldung.com/spring-boot-api-key-secret) More articles: [[<-- prev]](/spring-security-modules/spring-security-web-boot-3) From 7ec7ff98046b478c16f2a660e654045f3cdfae4e Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:27:58 +0800 Subject: [PATCH 30/40] Update README.md [skip ci] --- persistence-modules/spring-data-jpa-repo-3/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/spring-data-jpa-repo-3/README.md b/persistence-modules/spring-data-jpa-repo-3/README.md index 2ed2dc8896..93cc9379f7 100644 --- a/persistence-modules/spring-data-jpa-repo-3/README.md +++ b/persistence-modules/spring-data-jpa-repo-3/README.md @@ -6,4 +6,5 @@ This module contains articles about Spring Data JPA. - [New CRUD Repository Interfaces in Spring Data 3](https://www.baeldung.com/spring-data-3-crud-repository-interfaces) - [How to Persist a List of String in JPA?](https://www.baeldung.com/java-jpa-persist-string-list) - [Hibernate Natural IDs in Spring Boot](https://www.baeldung.com/spring-boot-hibernate-natural-ids) +- [Correct Use of flush() in JPA](https://www.baeldung.com/spring-jpa-flush) - More articles: [[<-- prev]](../spring-data-jpa-repo-2) From e41e0f203fb1c6b92481b999bacc9dc648f9be83 Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:31:53 +0800 Subject: [PATCH 31/40] Update README.md [skip ci] --- core-java-modules/core-java-collections-maps-6/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-collections-maps-6/README.md b/core-java-modules/core-java-collections-maps-6/README.md index fc12a1bb25..5b45752e74 100644 --- a/core-java-modules/core-java-collections-maps-6/README.md +++ b/core-java-modules/core-java-collections-maps-6/README.md @@ -1,2 +1,3 @@ ## Relevant Articles - [Copying All Keys and Values From One Hashmap Onto Another Without Replacing Existing Keys and Values](https://www.baeldung.com/java-copy-hashmap-no-changes) +- [Convert Hashmap to JSON Object in Java](https://www.baeldung.com/java-convert-hashmap-to-json-object) From 3a65bc85fdbdaa2c0d830f0d01bd44ca5e3e17cf Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:38:24 +0800 Subject: [PATCH 32/40] Update README.md [skip ci] --- xml-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/xml-2/README.md b/xml-2/README.md index 383d0763d4..e91078dbf0 100644 --- a/xml-2/README.md +++ b/xml-2/README.md @@ -6,3 +6,4 @@ This module contains articles about eXtensible Markup Language (XML) - [Pretty-Print XML in Java](https://www.baeldung.com/java-pretty-print-xml) - [Validate an XML File Against an XSD File](https://www.baeldung.com/java-validate-xml-xsd) +- [Converting JSON to XML in Java](https://www.baeldung.com/java-convert-json-to-xml) From 69febffe226ff49542719e909576698e0adee56d Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:40:51 +0800 Subject: [PATCH 33/40] Update README.md [skip ci] --- core-java-modules/core-java-io-apis-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-io-apis-2/README.md b/core-java-modules/core-java-io-apis-2/README.md index 7f04d6d028..d62fd3dbd1 100644 --- a/core-java-modules/core-java-io-apis-2/README.md +++ b/core-java-modules/core-java-io-apis-2/README.md @@ -13,3 +13,4 @@ This module contains articles about core Java input/output(IO) APIs. - [How to Take Input as String With Spaces in Java Using Scanner?](https://www.baeldung.com/java-scanner-input-with-spaces) - [Write Console Output to Text File in Java](https://www.baeldung.com/java-write-console-output-file) - [What’s the difference between Scanner next() and nextLine() methods?](https://www.baeldung.com/java-scanner-next-vs-nextline) +- [Handle NoSuchElementException When Reading a File Through Scanner](https://www.baeldung.com/java-scanner-nosuchelementexception-reading-file) From 1c21a5a221ea2c71f4198b7d5031a800814cc124 Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:43:47 +0800 Subject: [PATCH 34/40] Create README.md [skip ci] --- spring-boot-modules/spring-boot-gradle-2/README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 spring-boot-modules/spring-boot-gradle-2/README.md diff --git a/spring-boot-modules/spring-boot-gradle-2/README.md b/spring-boot-modules/spring-boot-gradle-2/README.md new file mode 100644 index 0000000000..ba6f30c000 --- /dev/null +++ b/spring-boot-modules/spring-boot-gradle-2/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [Configuring Gradle Tasks in Spring Boot 3](https://www.baeldung.com/spring-boot-3-gradle-configure-tasks) From 50cf2cee2384c83a579b66b56be5813b1443a644 Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:46:50 +0800 Subject: [PATCH 35/40] Update README.md [skip ci] --- core-java-modules/core-java-collections-list-5/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-collections-list-5/README.md b/core-java-modules/core-java-collections-list-5/README.md index 5c88f821f8..ff40ae3725 100644 --- a/core-java-modules/core-java-collections-list-5/README.md +++ b/core-java-modules/core-java-collections-list-5/README.md @@ -8,3 +8,4 @@ This module contains articles about the Java List collection - [Moving Items Around in an Arraylist](https://www.baeldung.com/java-arraylist-move-items) - [Check if a List Contains an Element From Another List in Java](https://www.baeldung.com/java-check-elements-between-lists) - [Array vs. List Performance in Java](https://www.baeldung.com/java-array-vs-list-performance) +- [Set Default Value for Elements in List](https://www.baeldung.com/java-list-set-default-values) From 100688ace245b6f2498d4e356669462b1e827869 Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 08:55:33 +0800 Subject: [PATCH 36/40] Update README.md [skip ci] --- core-java-modules/core-java-serialization/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-serialization/README.md b/core-java-modules/core-java-serialization/README.md index fc6cfcf134..27d515f855 100644 --- a/core-java-modules/core-java-serialization/README.md +++ b/core-java-modules/core-java-serialization/README.md @@ -7,3 +7,4 @@ - [Deserialization Vulnerabilities in Java](https://www.baeldung.com/java-deserialization-vulnerabilities) - [Serialization Validation in Java](https://www.baeldung.com/java-validate-serializable) - [What is the serialVersionUID?](http://www.baeldung.com/java-serial-version-uid) +- [Java Serialization: readObject() vs. readResolve()](https://www.baeldung.com/java-serialization-readobject-vs-readresolve) From df08d1d57a00353f848e8b87503c21d7f80451a6 Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 09:00:46 +0800 Subject: [PATCH 37/40] Update README.md [skip ci] --- apache-kafka-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/apache-kafka-2/README.md b/apache-kafka-2/README.md index e86504d605..159d631d61 100644 --- a/apache-kafka-2/README.md +++ b/apache-kafka-2/README.md @@ -9,3 +9,4 @@ You can build the project from the command line using: *mvn clean install*, or i - [Guide to Check if Apache Kafka Server Is Running](https://www.baeldung.com/apache-kafka-check-server-is-running) - [Add Custom Headers to a Kafka Message](https://www.baeldung.com/java-kafka-custom-headers) - [Get Last N Messages in Apache Kafka Topic](https://www.baeldung.com/java-apache-kafka-get-last-n-messages) +- [Is a Key Required as Part of Sending Messages to Kafka?](https://www.baeldung.com/java-kafka-message-key) From 6c1bfc5287f8161828384ec7f2685519018f6eae Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 09:05:22 +0800 Subject: [PATCH 38/40] Update README.md [skip ci] --- apache-kafka-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/apache-kafka-2/README.md b/apache-kafka-2/README.md index 159d631d61..9a5f6e15ae 100644 --- a/apache-kafka-2/README.md +++ b/apache-kafka-2/README.md @@ -10,3 +10,4 @@ You can build the project from the command line using: *mvn clean install*, or i - [Add Custom Headers to a Kafka Message](https://www.baeldung.com/java-kafka-custom-headers) - [Get Last N Messages in Apache Kafka Topic](https://www.baeldung.com/java-apache-kafka-get-last-n-messages) - [Is a Key Required as Part of Sending Messages to Kafka?](https://www.baeldung.com/java-kafka-message-key) +- [Read Data From the Beginning Using Kafka Consumer API](https://www.baeldung.com/java-kafka-consumer-api-read) From cb316df0f2dfa75dfe2412c0c8aea06d37f79d0c Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 09:12:34 +0800 Subject: [PATCH 39/40] Update README.md [skip ci] --- spring-boot-modules/spring-boot-properties-3/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot-modules/spring-boot-properties-3/README.md b/spring-boot-modules/spring-boot-properties-3/README.md index cb09a0ab81..476797965a 100644 --- a/spring-boot-modules/spring-boot-properties-3/README.md +++ b/spring-boot-modules/spring-boot-properties-3/README.md @@ -13,4 +13,5 @@ - [Using Environment Variables in Spring Boot’s application.properties](https://www.baeldung.com/spring-boot-properties-env-variables) - [Loading Multiple YAML Configuration Files in Spring Boot](https://www.baeldung.com/spring-boot-load-multiple-yaml-configuration-files) - [Using Environment Variables in Spring Boot’s Properties Files](https://www.baeldung.com/spring-boot-properties-env-variables) +- [Spring Boot Properties Prefix Must Be in Canonical Form](https://www.baeldung.com/spring-boot-properties-canonical-form) - More articles: [[<-- prev]](../spring-boot-properties-2) From bfd7a0ecf91610b0239d07c762fde981f99e1d5f Mon Sep 17 00:00:00 2001 From: edizor <113095366+edizor@users.noreply.github.com> Date: Fri, 2 Jun 2023 09:15:32 +0800 Subject: [PATCH 40/40] Update README.md [skip ci] --- testing-modules/testing-libraries-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/testing-modules/testing-libraries-2/README.md b/testing-modules/testing-libraries-2/README.md index 7cc08a8140..d075c40919 100644 --- a/testing-modules/testing-libraries-2/README.md +++ b/testing-modules/testing-libraries-2/README.md @@ -4,3 +4,4 @@ - [Guide to the System Stubs Library](https://www.baeldung.com/java-system-stubs) - [Code Coverage with SonarQube and JaCoCo](https://www.baeldung.com/sonarqube-jacoco-code-coverage) - [Exclusions from Jacoco Report](https://www.baeldung.com/jacoco-report-exclude) +- [Gray Box Testing Using the OAT Technique](https://www.baeldung.com/java-gray-box-orthogonal-array-testing)