From a6fc46e3f6ed643215ae21ca28d22b095c4a839c Mon Sep 17 00:00:00 2001 From: Gergo Petrik Date: Mon, 4 May 2020 16:40:20 +0200 Subject: [PATCH 01/46] ABA problem in concurrency --- .../java/com/baeldung/abaproblem/Account.java | 34 +++++++ .../baeldung/abaproblem/AccountUnitTest.java | 93 +++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java create mode 100644 core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java new file mode 100644 index 0000000000..0204c31fea --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java @@ -0,0 +1,34 @@ +package com.baeldung.abaproblem; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +public class Account { + + private AtomicInteger balance = new AtomicInteger(0); + + public int getBalance() { + return balance.get(); + } + + public boolean withdraw(int amount) throws InterruptedException { + int current = getBalance(); + if (current < amount) { + throw new RuntimeException("Not sufficient balance"); + } + precessBalance(); + return balance.compareAndSet(current, current - amount); + } + + private void precessBalance() throws InterruptedException { + if ("thread 1".equals(Thread.currentThread().getName())) { + TimeUnit.SECONDS.sleep(2); + } + } + + public boolean deposit(int amount) { + int current = balance.get(); + return balance.compareAndSet(current, current + amount); + } + +} diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java new file mode 100644 index 0000000000..ab88a0f447 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java @@ -0,0 +1,93 @@ +package com.baeldung.abaproblem; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class AccountUnitTest { + + private Account account; + + @BeforeEach + public void setUp() { + account = new Account(); + } + + @Test + public void zeroBalanceInitializationTest() { + assertEquals(0, account.getBalance()); + } + + @Test + public void depositTest() { + final int moneyToDeposit = 50; + + assertTrue(account.deposit(moneyToDeposit)); + + assertEquals(moneyToDeposit, account.getBalance()); + } + + @Test + public void withdrawTest() throws InterruptedException { + final int defaultBalance = 50; + final int moneyToWithdraw = 20; + + account.deposit(defaultBalance); + + assertTrue(account.withdraw(moneyToWithdraw)); + + assertEquals(defaultBalance - moneyToWithdraw, account.getBalance()); + } + + @Test + public void withdrawWithoutSufficientBalanceTest() { + assertThrows(RuntimeException.class, () -> account.withdraw(10)); + } + + @Test + public void abaProblemTest() throws InterruptedException { + final int defaultBalance = 50; + + final int amountToWithdrawByThreadA = 20; + final int amountToWithdrawByThreadB = 10; + final int amountToDepositByThreadB = 10; + + account.deposit(defaultBalance); + + Thread threadA = new Thread(() -> { + try { + // this will take longer due to the name of the thread + assertTrue(account.withdraw(amountToWithdrawByThreadA)); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }, "tread 1"); + + Thread threadB = new Thread(() -> { + + assertTrue(account.deposit(amountToDepositByThreadB)); + assertEquals(defaultBalance + amountToDepositByThreadB, account.getBalance()); + try { + // this will be fast due to the name of the thread + assertTrue(account.withdraw(amountToWithdrawByThreadB)); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + // thread 1 didn't finish yet, so the original value will be in place for it + assertEquals(defaultBalance, account.getBalance()); + + }, "thread 2"); + + threadA.start(); + threadB.start(); + threadA.join(); + threadB.join(); + + // compareAndSet operation succeeds for thread 1 + assertEquals(defaultBalance - amountToWithdrawByThreadA, account.getBalance()); + } +} From 68dc88528e488db5aef951d8578bcfb33c46cd81 Mon Sep 17 00:00:00 2001 From: Gergo Petrik Date: Thu, 7 May 2020 11:45:40 +0200 Subject: [PATCH 02/46] added transaction recording --- .../java/com/baeldung/abaproblem/Account.java | 21 ++++++++++++++++--- .../baeldung/abaproblem/AccountUnitTest.java | 14 +++++++++++-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java index 0204c31fea..558245283a 100644 --- a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java +++ b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java @@ -1,34 +1,49 @@ package com.baeldung.abaproblem; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class Account { private AtomicInteger balance = new AtomicInteger(0); + private List transactionDates = new ArrayList<>(); public int getBalance() { return balance.get(); } + public List getTransactionDates() { + return transactionDates; + } + public boolean withdraw(int amount) throws InterruptedException { int current = getBalance(); if (current < amount) { throw new RuntimeException("Not sufficient balance"); } precessBalance(); - return balance.compareAndSet(current, current - amount); + boolean result = balance.compareAndSet(current, current - amount); + if (result) { + transactionDates.add(System.currentTimeMillis()); + } + return result; } private void precessBalance() throws InterruptedException { - if ("thread 1".equals(Thread.currentThread().getName())) { + if ("thread1".equals(Thread.currentThread().getName())) { TimeUnit.SECONDS.sleep(2); } } public boolean deposit(int amount) { int current = balance.get(); - return balance.compareAndSet(current, current + amount); + boolean result = balance.compareAndSet(current, current + amount); + if (result) { + transactionDates.add(System.currentTimeMillis()); + } + return result; } } diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java index ab88a0f447..457580b96c 100644 --- a/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java +++ b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -19,6 +20,7 @@ public class AccountUnitTest { @Test public void zeroBalanceInitializationTest() { assertEquals(0, account.getBalance()); + assertTrue(account.getTransactionDates().isEmpty()); } @Test @@ -55,7 +57,9 @@ public class AccountUnitTest { final int amountToWithdrawByThreadB = 10; final int amountToDepositByThreadB = 10; + assertTrue(account.getTransactionDates().isEmpty()); account.deposit(defaultBalance); + assertEquals(1, account.getTransactionDates().size()); Thread threadA = new Thread(() -> { try { @@ -64,7 +68,7 @@ public class AccountUnitTest { } catch (InterruptedException e) { throw new RuntimeException(e); } - }, "tread 1"); + }, "thread1"); Thread threadB = new Thread(() -> { @@ -80,7 +84,7 @@ public class AccountUnitTest { // thread 1 didn't finish yet, so the original value will be in place for it assertEquals(defaultBalance, account.getBalance()); - }, "thread 2"); + }, "thread2"); threadA.start(); threadB.start(); @@ -89,5 +93,11 @@ public class AccountUnitTest { // compareAndSet operation succeeds for thread 1 assertEquals(defaultBalance - amountToWithdrawByThreadA, account.getBalance()); + + //but there are other transactions + assertNotEquals(2, account.getTransactionDates().size()); + + // thread 2 did two modifications as well + assertEquals(4, account.getTransactionDates().size()); } } From 69c50660de908d542a87bb2f9ca3896ba7c3f5ca Mon Sep 17 00:00:00 2001 From: Justin Albano Date: Sun, 10 May 2020 09:47:28 -0400 Subject: [PATCH 03/46] BAEL-3951: Added JDK 14 record example and associated tests. --- .../com/baeldung/java14/record/Person.java | 22 +++ .../baeldung/java14/record/PersonTest.java | 150 ++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 core-java-modules/core-java-14/src/main/java/com/baeldung/java14/record/Person.java create mode 100644 core-java-modules/core-java-14/src/test/java/com/baeldung/java14/record/PersonTest.java diff --git a/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/record/Person.java b/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/record/Person.java new file mode 100644 index 0000000000..33243c4ecf --- /dev/null +++ b/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/record/Person.java @@ -0,0 +1,22 @@ +package com.baeldung.java14.record; + +import java.util.Objects; + +public record Person (String name, String address) { + + public static String UNKWOWN_ADDRESS = "Unknown"; + public static String UNNAMED = "Unnamed"; + + public Person { + Objects.requireNonNull(name); + Objects.requireNonNull(address); + } + + public Person(String name) { + this(name, UNKWOWN_ADDRESS); + } + + public static Person unnamed(String address) { + return new Person(UNNAMED, address); + } +} diff --git a/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/record/PersonTest.java b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/record/PersonTest.java new file mode 100644 index 0000000000..4a7d4ede5f --- /dev/null +++ b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/record/PersonTest.java @@ -0,0 +1,150 @@ +package com.baeldung.java14.record; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class PersonTest { + + @Test + public void givenSameNameAndAddress_whenEquals_thenPersonsEqual() { + + String name = "John Doe"; + String address = "100 Linda Ln."; + + Person person1 = new Person(name, address); + Person person2 = new Person(name, address); + + assertTrue(person1.equals(person2)); + } + + @Test + public void givenDifferentObject_whenEquals_thenNotEqual() { + + Person person = new Person("John Doe", "100 Linda Ln."); + + assertFalse(person.equals(new Object())); + } + + @Test + public void givenDifferentName_whenEquals_thenPersonsNotEqual() { + + String address = "100 Linda Ln."; + + Person person1 = new Person("Jane Doe", address); + Person person2 = new Person("John Doe", address); + + assertFalse(person1.equals(person2)); + } + + @Test + public void givenDifferentAddress_whenEquals_thenPersonsNotEqual() { + + String name = "John Doe"; + + Person person1 = new Person(name, "100 Linda Ln."); + Person person2 = new Person(name, "200 London Ave."); + + assertFalse(person1.equals(person2)); + } + + @Test + public void givenSameNameAndAddress_whenHashCode_thenPersonsEqual() { + + String name = "John Doe"; + String address = "100 Linda Ln."; + + Person person1 = new Person(name, address); + Person person2 = new Person(name, address); + + assertEquals(person1.hashCode(), person2.hashCode()); + } + + @Test + public void givenDifferentObject_whenHashCode_thenNotEqual() { + + Person person = new Person("John Doe", "100 Linda Ln."); + + assertNotEquals(person.hashCode(), new Object().hashCode()); + } + + @Test + public void givenDifferentName_whenHashCode_thenPersonsNotEqual() { + + String address = "100 Linda Ln."; + + Person person1 = new Person("Jane Doe", address); + Person person2 = new Person("John Doe", address); + + assertNotEquals(person1.hashCode(), person2.hashCode()); + } + + @Test + public void givenDifferentAddress_whenHashCode_thenPersonsNotEqual() { + + String name = "John Doe"; + + Person person1 = new Person(name, "100 Linda Ln."); + Person person2 = new Person(name, "200 London Ave."); + + assertNotEquals(person1.hashCode(), person2.hashCode()); + } + + @Test + public void givenValidNameAndAddress_whenGetNameAndAddress_thenExpectedValuesReturned() { + + String name = "John Doe"; + String address = "100 Linda Ln."; + + Person person = new Person(name, address); + + assertEquals(name, person.name()); + assertEquals(address, person.address()); + } + + @Test + public void givenValidNameAndAddress_whenToString_thenCorrectStringReturned() { + + String name = "John Doe"; + String address = "100 Linda Ln."; + + Person person = new Person(name, address); + + assertEquals("Person[name=" + name + ", address=" + address + "]", person.toString()); + } + + @Test(expected = NullPointerException.class) + public void givenNullName_whenConstruct_thenErrorThrown() { + new Person(null, "100 Linda Ln."); + } + + @Test(expected = NullPointerException.class) + public void givenNullAddress_whenConstruct_thenErrorThrown() { + new Person("John Doe", null); + } + + @Test + public void givenUnknownAddress_whenConstructing_thenAddressPopulated() { + + String name = "John Doe"; + + Person person = new Person(name); + + assertEquals(name, person.name()); + assertEquals(Person.UNKWOWN_ADDRESS, person.address()); + } + + @Test + public void givenUnnamed_whenConstructingThroughFactory_thenNamePopulated() { + + String address = "100 Linda Ln."; + + Person person = Person.unnamed(address); + + assertEquals(Person.UNNAMED, person.name()); + assertEquals(address, person.address()); + } +} From 48d1c94dc0942a5b2e111c1af02260adc19df174 Mon Sep 17 00:00:00 2001 From: Justin Albano Date: Wed, 13 May 2020 06:06:58 -0400 Subject: [PATCH 04/46] BAEL-3951: Corrected misspelling. --- .../com/baeldung/java14/record/Person.java | 44 +-- .../baeldung/java14/record/PersonTest.java | 300 +++++++++--------- 2 files changed, 172 insertions(+), 172 deletions(-) diff --git a/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/record/Person.java b/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/record/Person.java index 33243c4ecf..56cc9f30d9 100644 --- a/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/record/Person.java +++ b/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/record/Person.java @@ -1,22 +1,22 @@ -package com.baeldung.java14.record; - -import java.util.Objects; - -public record Person (String name, String address) { - - public static String UNKWOWN_ADDRESS = "Unknown"; - public static String UNNAMED = "Unnamed"; - - public Person { - Objects.requireNonNull(name); - Objects.requireNonNull(address); - } - - public Person(String name) { - this(name, UNKWOWN_ADDRESS); - } - - public static Person unnamed(String address) { - return new Person(UNNAMED, address); - } -} +package com.baeldung.java14.record; + +import java.util.Objects; + +public record Person (String name, String address) { + + public static String UNKNOWN_ADDRESS = "Unknown"; + public static String UNNAMED = "Unnamed"; + + public Person { + Objects.requireNonNull(name); + Objects.requireNonNull(address); + } + + public Person(String name) { + this(name, UNKNOWN_ADDRESS); + } + + public static Person unnamed(String address) { + return new Person(UNNAMED, address); + } +} diff --git a/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/record/PersonTest.java b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/record/PersonTest.java index 4a7d4ede5f..2a5195efc1 100644 --- a/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/record/PersonTest.java +++ b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/record/PersonTest.java @@ -1,150 +1,150 @@ -package com.baeldung.java14.record; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class PersonTest { - - @Test - public void givenSameNameAndAddress_whenEquals_thenPersonsEqual() { - - String name = "John Doe"; - String address = "100 Linda Ln."; - - Person person1 = new Person(name, address); - Person person2 = new Person(name, address); - - assertTrue(person1.equals(person2)); - } - - @Test - public void givenDifferentObject_whenEquals_thenNotEqual() { - - Person person = new Person("John Doe", "100 Linda Ln."); - - assertFalse(person.equals(new Object())); - } - - @Test - public void givenDifferentName_whenEquals_thenPersonsNotEqual() { - - String address = "100 Linda Ln."; - - Person person1 = new Person("Jane Doe", address); - Person person2 = new Person("John Doe", address); - - assertFalse(person1.equals(person2)); - } - - @Test - public void givenDifferentAddress_whenEquals_thenPersonsNotEqual() { - - String name = "John Doe"; - - Person person1 = new Person(name, "100 Linda Ln."); - Person person2 = new Person(name, "200 London Ave."); - - assertFalse(person1.equals(person2)); - } - - @Test - public void givenSameNameAndAddress_whenHashCode_thenPersonsEqual() { - - String name = "John Doe"; - String address = "100 Linda Ln."; - - Person person1 = new Person(name, address); - Person person2 = new Person(name, address); - - assertEquals(person1.hashCode(), person2.hashCode()); - } - - @Test - public void givenDifferentObject_whenHashCode_thenNotEqual() { - - Person person = new Person("John Doe", "100 Linda Ln."); - - assertNotEquals(person.hashCode(), new Object().hashCode()); - } - - @Test - public void givenDifferentName_whenHashCode_thenPersonsNotEqual() { - - String address = "100 Linda Ln."; - - Person person1 = new Person("Jane Doe", address); - Person person2 = new Person("John Doe", address); - - assertNotEquals(person1.hashCode(), person2.hashCode()); - } - - @Test - public void givenDifferentAddress_whenHashCode_thenPersonsNotEqual() { - - String name = "John Doe"; - - Person person1 = new Person(name, "100 Linda Ln."); - Person person2 = new Person(name, "200 London Ave."); - - assertNotEquals(person1.hashCode(), person2.hashCode()); - } - - @Test - public void givenValidNameAndAddress_whenGetNameAndAddress_thenExpectedValuesReturned() { - - String name = "John Doe"; - String address = "100 Linda Ln."; - - Person person = new Person(name, address); - - assertEquals(name, person.name()); - assertEquals(address, person.address()); - } - - @Test - public void givenValidNameAndAddress_whenToString_thenCorrectStringReturned() { - - String name = "John Doe"; - String address = "100 Linda Ln."; - - Person person = new Person(name, address); - - assertEquals("Person[name=" + name + ", address=" + address + "]", person.toString()); - } - - @Test(expected = NullPointerException.class) - public void givenNullName_whenConstruct_thenErrorThrown() { - new Person(null, "100 Linda Ln."); - } - - @Test(expected = NullPointerException.class) - public void givenNullAddress_whenConstruct_thenErrorThrown() { - new Person("John Doe", null); - } - - @Test - public void givenUnknownAddress_whenConstructing_thenAddressPopulated() { - - String name = "John Doe"; - - Person person = new Person(name); - - assertEquals(name, person.name()); - assertEquals(Person.UNKWOWN_ADDRESS, person.address()); - } - - @Test - public void givenUnnamed_whenConstructingThroughFactory_thenNamePopulated() { - - String address = "100 Linda Ln."; - - Person person = Person.unnamed(address); - - assertEquals(Person.UNNAMED, person.name()); - assertEquals(address, person.address()); - } -} +package com.baeldung.java14.record; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class PersonTest { + + @Test + public void givenSameNameAndAddress_whenEquals_thenPersonsEqual() { + + String name = "John Doe"; + String address = "100 Linda Ln."; + + Person person1 = new Person(name, address); + Person person2 = new Person(name, address); + + assertTrue(person1.equals(person2)); + } + + @Test + public void givenDifferentObject_whenEquals_thenNotEqual() { + + Person person = new Person("John Doe", "100 Linda Ln."); + + assertFalse(person.equals(new Object())); + } + + @Test + public void givenDifferentName_whenEquals_thenPersonsNotEqual() { + + String address = "100 Linda Ln."; + + Person person1 = new Person("Jane Doe", address); + Person person2 = new Person("John Doe", address); + + assertFalse(person1.equals(person2)); + } + + @Test + public void givenDifferentAddress_whenEquals_thenPersonsNotEqual() { + + String name = "John Doe"; + + Person person1 = new Person(name, "100 Linda Ln."); + Person person2 = new Person(name, "200 London Ave."); + + assertFalse(person1.equals(person2)); + } + + @Test + public void givenSameNameAndAddress_whenHashCode_thenPersonsEqual() { + + String name = "John Doe"; + String address = "100 Linda Ln."; + + Person person1 = new Person(name, address); + Person person2 = new Person(name, address); + + assertEquals(person1.hashCode(), person2.hashCode()); + } + + @Test + public void givenDifferentObject_whenHashCode_thenNotEqual() { + + Person person = new Person("John Doe", "100 Linda Ln."); + + assertNotEquals(person.hashCode(), new Object().hashCode()); + } + + @Test + public void givenDifferentName_whenHashCode_thenPersonsNotEqual() { + + String address = "100 Linda Ln."; + + Person person1 = new Person("Jane Doe", address); + Person person2 = new Person("John Doe", address); + + assertNotEquals(person1.hashCode(), person2.hashCode()); + } + + @Test + public void givenDifferentAddress_whenHashCode_thenPersonsNotEqual() { + + String name = "John Doe"; + + Person person1 = new Person(name, "100 Linda Ln."); + Person person2 = new Person(name, "200 London Ave."); + + assertNotEquals(person1.hashCode(), person2.hashCode()); + } + + @Test + public void givenValidNameAndAddress_whenGetNameAndAddress_thenExpectedValuesReturned() { + + String name = "John Doe"; + String address = "100 Linda Ln."; + + Person person = new Person(name, address); + + assertEquals(name, person.name()); + assertEquals(address, person.address()); + } + + @Test + public void givenValidNameAndAddress_whenToString_thenCorrectStringReturned() { + + String name = "John Doe"; + String address = "100 Linda Ln."; + + Person person = new Person(name, address); + + assertEquals("Person[name=" + name + ", address=" + address + "]", person.toString()); + } + + @Test(expected = NullPointerException.class) + public void givenNullName_whenConstruct_thenErrorThrown() { + new Person(null, "100 Linda Ln."); + } + + @Test(expected = NullPointerException.class) + public void givenNullAddress_whenConstruct_thenErrorThrown() { + new Person("John Doe", null); + } + + @Test + public void givenUnknownAddress_whenConstructing_thenAddressPopulated() { + + String name = "John Doe"; + + Person person = new Person(name); + + assertEquals(name, person.name()); + assertEquals(Person.UNKNOWN_ADDRESS, person.address()); + } + + @Test + public void givenUnnamed_whenConstructingThroughFactory_thenNamePopulated() { + + String address = "100 Linda Ln."; + + Person person = Person.unnamed(address); + + assertEquals(Person.UNNAMED, person.name()); + assertEquals(address, person.address()); + } +} From 12ef94be3959112f2b177c570b33c77cc09264b2 Mon Sep 17 00:00:00 2001 From: Gergo Petrik Date: Sun, 17 May 2020 10:07:47 +0200 Subject: [PATCH 05/46] added revision number and cas failure count --- .../java/com/baeldung/abaproblem/Account.java | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java index 558245283a..ee1bdcd55b 100644 --- a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java +++ b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/abaproblem/Account.java @@ -1,39 +1,53 @@ package com.baeldung.abaproblem; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class Account { - private AtomicInteger balance = new AtomicInteger(0); - private List transactionDates = new ArrayList<>(); + private AtomicInteger balance; + private AtomicInteger transactionCount; + private ThreadLocal currentThreadCASFailureCount; + + public Account() { + this.balance = new AtomicInteger(0); + this.transactionCount = new AtomicInteger(0); + this.currentThreadCASFailureCount = new ThreadLocal<>(); + this.currentThreadCASFailureCount.set(0); + } public int getBalance() { return balance.get(); } - public List getTransactionDates() { - return transactionDates; + public int getTransactionCount() { + return transactionCount.get(); } - public boolean withdraw(int amount) throws InterruptedException { + public int getCurrentThreadCASFailureCount() { + return currentThreadCASFailureCount.get(); + } + + public boolean withdraw(int amount) { int current = getBalance(); - if (current < amount) { - throw new RuntimeException("Not sufficient balance"); - } - precessBalance(); + maybeWait(); boolean result = balance.compareAndSet(current, current - amount); if (result) { - transactionDates.add(System.currentTimeMillis()); + transactionCount.incrementAndGet(); + } else { + int currentCASFailureCount = currentThreadCASFailureCount.get(); + currentThreadCASFailureCount.set(currentCASFailureCount + 1); } return result; } - private void precessBalance() throws InterruptedException { + private void maybeWait() { if ("thread1".equals(Thread.currentThread().getName())) { - TimeUnit.SECONDS.sleep(2); + try { + TimeUnit.SECONDS.sleep(2); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } } } @@ -41,7 +55,10 @@ public class Account { int current = balance.get(); boolean result = balance.compareAndSet(current, current + amount); if (result) { - transactionDates.add(System.currentTimeMillis()); + transactionCount.incrementAndGet(); + } else { + int currentCASFailureCount = currentThreadCASFailureCount.get(); + currentThreadCASFailureCount.set(currentCASFailureCount + 1); } return result; } From c9453fe33a0a296e6d41161b9fb4b6e27ecd3bef Mon Sep 17 00:00:00 2001 From: Gergo Petrik Date: Mon, 18 May 2020 16:33:03 +0200 Subject: [PATCH 06/46] adding account unit test --- .../baeldung/abaproblem/AccountUnitTest.java | 65 +++++++++---------- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java index 457580b96c..aa5f0f7997 100644 --- a/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java +++ b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/abaproblem/AccountUnitTest.java @@ -5,7 +5,6 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; public class AccountUnitTest { @@ -20,7 +19,8 @@ public class AccountUnitTest { @Test public void zeroBalanceInitializationTest() { assertEquals(0, account.getBalance()); - assertTrue(account.getTransactionDates().isEmpty()); + assertEquals(0, account.getTransactionCount()); + assertEquals(0, account.getCurrentThreadCASFailureCount()); } @Test @@ -44,60 +44,55 @@ public class AccountUnitTest { assertEquals(defaultBalance - moneyToWithdraw, account.getBalance()); } - @Test - public void withdrawWithoutSufficientBalanceTest() { - assertThrows(RuntimeException.class, () -> account.withdraw(10)); - } - @Test public void abaProblemTest() throws InterruptedException { final int defaultBalance = 50; - final int amountToWithdrawByThreadA = 20; - final int amountToWithdrawByThreadB = 10; - final int amountToDepositByThreadB = 10; + final int amountToWithdrawByThread1 = 20; + final int amountToWithdrawByThread2 = 10; + final int amountToDepositByThread2 = 10; - assertTrue(account.getTransactionDates().isEmpty()); + assertEquals(0, account.getTransactionCount()); + assertEquals(0, account.getCurrentThreadCASFailureCount()); account.deposit(defaultBalance); - assertEquals(1, account.getTransactionDates().size()); + assertEquals(1, account.getTransactionCount()); + + Thread thread1 = new Thread(() -> { + + // this will take longer due to the name of the thread + assertTrue(account.withdraw(amountToWithdrawByThread1)); + + // thread 1 fails to capture ABA problem + assertNotEquals(1, account.getCurrentThreadCASFailureCount()); - Thread threadA = new Thread(() -> { - try { - // this will take longer due to the name of the thread - assertTrue(account.withdraw(amountToWithdrawByThreadA)); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } }, "thread1"); - Thread threadB = new Thread(() -> { + Thread thread2 = new Thread(() -> { - assertTrue(account.deposit(amountToDepositByThreadB)); - assertEquals(defaultBalance + amountToDepositByThreadB, account.getBalance()); - try { - // this will be fast due to the name of the thread - assertTrue(account.withdraw(amountToWithdrawByThreadB)); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + assertTrue(account.deposit(amountToDepositByThread2)); + assertEquals(defaultBalance + amountToDepositByThread2, account.getBalance()); + + // this will be fast due to the name of the thread + assertTrue(account.withdraw(amountToWithdrawByThread2)); // thread 1 didn't finish yet, so the original value will be in place for it assertEquals(defaultBalance, account.getBalance()); + assertEquals(0, account.getCurrentThreadCASFailureCount()); }, "thread2"); - threadA.start(); - threadB.start(); - threadA.join(); - threadB.join(); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); // compareAndSet operation succeeds for thread 1 - assertEquals(defaultBalance - amountToWithdrawByThreadA, account.getBalance()); + assertEquals(defaultBalance - amountToWithdrawByThread1, account.getBalance()); //but there are other transactions - assertNotEquals(2, account.getTransactionDates().size()); + assertNotEquals(2, account.getTransactionCount()); // thread 2 did two modifications as well - assertEquals(4, account.getTransactionDates().size()); + assertEquals(4, account.getTransactionCount()); } } From 8f1de1c3b702a07307e172b8745ece9c116f5f05 Mon Sep 17 00:00:00 2001 From: Chirag Dewan Date: Sun, 24 May 2020 13:58:50 +0530 Subject: [PATCH 07/46] BAEL3889 - Kafka Mock Producer --- .../baeldung/kafka/EvenOddPartitioner.java | 16 +++ .../com/baeldung/kafka/KafkaProducer.java | 40 ++++++ .../baeldung/kafka/KafkaProducerUnitTest.java | 114 ++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 libraries/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java create mode 100644 libraries/src/main/java/com/baeldung/kafka/KafkaProducer.java create mode 100644 libraries/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java diff --git a/libraries/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java b/libraries/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java new file mode 100644 index 0000000000..12c86828dd --- /dev/null +++ b/libraries/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java @@ -0,0 +1,16 @@ +package com.baeldung.kafka; + +import org.apache.kafka.clients.producer.internals.DefaultPartitioner; +import org.apache.kafka.common.Cluster; + +public class EvenOddPartitioner extends DefaultPartitioner { + + @Override + public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) { + + if (((String)key).length() % 2 == 0) + return 0; + + return 1; + } +} diff --git a/libraries/src/main/java/com/baeldung/kafka/KafkaProducer.java b/libraries/src/main/java/com/baeldung/kafka/KafkaProducer.java new file mode 100644 index 0000000000..8574cd1c40 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/kafka/KafkaProducer.java @@ -0,0 +1,40 @@ +package com.baeldung.kafka; + +import org.apache.kafka.clients.producer.Producer; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.clients.producer.RecordMetadata; + +import java.util.concurrent.Future; + +public class KafkaProducer { + + private final Producer producer; + + public KafkaProducer(Producer producer) { + this.producer = producer; + } + + public Future send(String key, String value) { + ProducerRecord record = new ProducerRecord("topic_sports_news", + key, value); + return producer.send(record); + } + + public void flush() { + producer.flush(); + } + + public void beginTransaction() { + producer.beginTransaction(); + } + + public void initTransaction() { + producer.initTransactions(); + } + + public void commitTransaction() { + producer.commitTransaction(); + } + + +} diff --git a/libraries/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java b/libraries/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java new file mode 100644 index 0000000000..ce3803322c --- /dev/null +++ b/libraries/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java @@ -0,0 +1,114 @@ +package com.baeldung.kafka; + +import org.apache.kafka.clients.producer.MockProducer; +import org.apache.kafka.clients.producer.RecordMetadata; +import org.apache.kafka.common.Cluster; +import org.apache.kafka.common.Node; +import org.apache.kafka.common.PartitionInfo; +import org.apache.kafka.common.serialization.StringSerializer; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import static java.util.Collections.emptySet; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class KafkaProducerUnitTest { + + private final String TOPIC_NAME = "topic_sports_news"; + + private KafkaProducer kafkaProducer; + private MockProducer mockProducer; + + private void buildMockProducer(boolean autoComplete) { + this.mockProducer = new MockProducer<>(autoComplete, new StringSerializer(), new StringSerializer()); + } + + @Test + void givenKeyValue_whenSend_thenVerifyHistory() throws ExecutionException, InterruptedException { + + buildMockProducer(true); + //when + kafkaProducer = new KafkaProducer(mockProducer); + Future recordMetadataFuture = kafkaProducer.send("data", "{\"site\" : \"baeldung\"}"); + + //then + assertTrue(mockProducer.history().size() == 1); + assertTrue(mockProducer.history().get(0).key().equalsIgnoreCase("data")); + assertTrue(recordMetadataFuture.get().partition() == 0); + + } + + @Test + void givenKeyValue_whenSend_thenSendOnlyAfterFlush() { + + buildMockProducer(false); + //when + kafkaProducer = new KafkaProducer(mockProducer); + Future record = kafkaProducer.send("data", "{\"site\" : \"baeldung\"}"); + assertFalse(record.isDone()); + + //then + kafkaProducer.flush(); + assertTrue(record.isDone()); + } + + @Test + void givenKeyValue_whenSend_thenReturnException() { + + buildMockProducer(false); + //when + kafkaProducer = new KafkaProducer(mockProducer); + Future record = kafkaProducer.send("site", "{\"site\" : \"baeldung\"}"); + RuntimeException e = new RuntimeException(); + mockProducer.errorNext(e); + //then + try { + record.get(); + } catch (ExecutionException | InterruptedException ex) { + assertEquals(e, ex.getCause()); + } + assertTrue(record.isDone()); + } + + @Test + void givenKeyValue_whenSendWithTxn_thenSendOnlyOnTxnCommit() { + + buildMockProducer(true); + //when + kafkaProducer = new KafkaProducer(mockProducer); + kafkaProducer.initTransaction(); + kafkaProducer.beginTransaction(); + Future record = kafkaProducer.send("data", "{\"site\" : \"baeldung\"}"); + + //then + assertTrue(mockProducer.history().isEmpty()); + kafkaProducer.commitTransaction(); + assertTrue(mockProducer.history().size() == 1); + } + + @Test + void givenKeyValue_whenSendWithPartitioning_thenVerifyPartitionNumber() throws ExecutionException, InterruptedException { + + PartitionInfo partitionInfo0 = new PartitionInfo(TOPIC_NAME, 0, null, null, null); + PartitionInfo partitionInfo1 = new PartitionInfo(TOPIC_NAME, 1, null, null, null); + List list = new ArrayList<>(); + list.add(partitionInfo0); + list.add(partitionInfo1); + Cluster cluster = new Cluster("kafkab", new ArrayList(), list, emptySet(), emptySet()); + this.mockProducer = new MockProducer<>(cluster, true, new EvenOddPartitioner(), new StringSerializer(), new StringSerializer()); + //when + kafkaProducer = new KafkaProducer(mockProducer); + Future recordMetadataFuture = kafkaProducer.send("partition", "{\"site\" : \"baeldung\"}"); + + //then + assertTrue(recordMetadataFuture.get().partition() == 1); + + } + +} \ No newline at end of file From 7943a59707c9534e2f24c90106b32efdcc771dbe Mon Sep 17 00:00:00 2001 From: Chirag Dewan Date: Tue, 26 May 2020 17:23:59 +0530 Subject: [PATCH 08/46] BAEL3889 - Kafka Mock Producer --- .../src/main/java/com/baeldung/kafka/EvenOddPartitioner.java | 0 .../src/main/java/com/baeldung/kafka/KafkaProducer.java | 0 .../src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename {libraries => libraries-6}/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java (100%) rename {libraries => libraries-6}/src/main/java/com/baeldung/kafka/KafkaProducer.java (100%) rename {libraries => libraries-6}/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java (100%) diff --git a/libraries/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java b/libraries-6/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java similarity index 100% rename from libraries/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java rename to libraries-6/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java diff --git a/libraries/src/main/java/com/baeldung/kafka/KafkaProducer.java b/libraries-6/src/main/java/com/baeldung/kafka/KafkaProducer.java similarity index 100% rename from libraries/src/main/java/com/baeldung/kafka/KafkaProducer.java rename to libraries-6/src/main/java/com/baeldung/kafka/KafkaProducer.java diff --git a/libraries/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java b/libraries-6/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java rename to libraries-6/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java From 75a44b99652b87b3c3c7781a50dd8b6767e24ce7 Mon Sep 17 00:00:00 2001 From: Chirag Dewan Date: Sun, 31 May 2020 18:39:20 +0530 Subject: [PATCH 09/46] BAEL3889 - Kafka Mock Producer --- libraries-data-2/pom.xml | 7 +++++++ .../main/java/com/baeldung/kafka/EvenOddPartitioner.java | 0 .../src/main/java/com/baeldung/kafka/KafkaProducer.java | 0 .../java/com/baeldung/kafka/KafkaProducerUnitTest.java | 0 4 files changed, 7 insertions(+) rename {libraries-6 => libraries-data-2}/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java (100%) rename {libraries-6 => libraries-data-2}/src/main/java/com/baeldung/kafka/KafkaProducer.java (100%) rename {libraries-6 => libraries-data-2}/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java (100%) diff --git a/libraries-data-2/pom.xml b/libraries-data-2/pom.xml index bdfb2c5ed6..2d27ec2107 100644 --- a/libraries-data-2/pom.xml +++ b/libraries-data-2/pom.xml @@ -153,6 +153,13 @@ renjin-script-engine ${renjin.version} + + org.apache.kafka + kafka-clients + ${kafka.version} + test + test + diff --git a/libraries-6/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java b/libraries-data-2/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java similarity index 100% rename from libraries-6/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java rename to libraries-data-2/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java diff --git a/libraries-6/src/main/java/com/baeldung/kafka/KafkaProducer.java b/libraries-data-2/src/main/java/com/baeldung/kafka/KafkaProducer.java similarity index 100% rename from libraries-6/src/main/java/com/baeldung/kafka/KafkaProducer.java rename to libraries-data-2/src/main/java/com/baeldung/kafka/KafkaProducer.java diff --git a/libraries-6/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java b/libraries-data-2/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java similarity index 100% rename from libraries-6/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java rename to libraries-data-2/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java From e245b2eca3347f02e0ab45011ffc8b1c880f01f3 Mon Sep 17 00:00:00 2001 From: Chirag Dewan Date: Sun, 31 May 2020 18:59:54 +0530 Subject: [PATCH 10/46] BAEL3889 - Changing the package structure --- .../com/baeldung/kafka/{ => producer}/EvenOddPartitioner.java | 0 .../java/com/baeldung/kafka/{ => producer}/KafkaProducer.java | 0 .../com/baeldung/kafka/{ => producer}/KafkaProducerUnitTest.java | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename libraries-data-2/src/main/java/com/baeldung/kafka/{ => producer}/EvenOddPartitioner.java (100%) rename libraries-data-2/src/main/java/com/baeldung/kafka/{ => producer}/KafkaProducer.java (100%) rename libraries-data-2/src/test/java/com/baeldung/kafka/{ => producer}/KafkaProducerUnitTest.java (100%) diff --git a/libraries-data-2/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java b/libraries-data-2/src/main/java/com/baeldung/kafka/producer/EvenOddPartitioner.java similarity index 100% rename from libraries-data-2/src/main/java/com/baeldung/kafka/EvenOddPartitioner.java rename to libraries-data-2/src/main/java/com/baeldung/kafka/producer/EvenOddPartitioner.java diff --git a/libraries-data-2/src/main/java/com/baeldung/kafka/KafkaProducer.java b/libraries-data-2/src/main/java/com/baeldung/kafka/producer/KafkaProducer.java similarity index 100% rename from libraries-data-2/src/main/java/com/baeldung/kafka/KafkaProducer.java rename to libraries-data-2/src/main/java/com/baeldung/kafka/producer/KafkaProducer.java diff --git a/libraries-data-2/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java b/libraries-data-2/src/test/java/com/baeldung/kafka/producer/KafkaProducerUnitTest.java similarity index 100% rename from libraries-data-2/src/test/java/com/baeldung/kafka/KafkaProducerUnitTest.java rename to libraries-data-2/src/test/java/com/baeldung/kafka/producer/KafkaProducerUnitTest.java From 00b67725ea441900eb1810d7e1717c3a45f3762b Mon Sep 17 00:00:00 2001 From: dupirefr Date: Sat, 30 May 2020 17:27:37 +0200 Subject: [PATCH 11/46] [JAVA-1659] Upgraded Maven Surefire Plugin and JUnit versions * Upgraded Maven Surefire Plugin version to 2.22.2 * Upgraded JUnit version to 5.6.2 * Imported JUnit BOM before Spring Boot Dependencies BOM (as explained [here](https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/maven-plugin/reference/html/#using)) --- ddd/pom.xml | 54 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/ddd/pom.xml b/ddd/pom.xml index 1253f2ac48..422f9ccd15 100644 --- a/ddd/pom.xml +++ b/ddd/pom.xml @@ -17,6 +17,35 @@ ../parent-boot-2 + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + + + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + org.springframework.boot @@ -26,24 +55,6 @@ org.springframework.boot spring-boot-starter-data-cassandra - - org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - - - org.junit.platform - junit-platform-launcher - ${junit-platform.version} - test - org.joda joda-money @@ -95,7 +106,10 @@ - 1.0.1 - + 2.22.2 + 1.0.1 + + 5.6.2 + From 3086da7d127b92c19b51d9a829c08055bccefd54 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Mon, 1 Jun 2020 11:11:12 +0200 Subject: [PATCH 12/46] [JAVA-1659] Upgraded Maven Surefire Plugin and JUnit versions * Fixed sub-modules parent poms names * Added relative paths to sub-modules poms * Configured Maven Surefire Plugin so that it works with the dummy test * Upgraded Maven Surefire Plugin version to 2.22.2 * Upgraded JUnit version to 5.6.2 --- ddd-modules/infrastructure/pom.xml | 3 ++- ddd-modules/mainapp/pom.xml | 3 ++- ddd-modules/ordercontext/pom.xml | 3 ++- ddd-modules/pom.xml | 34 ++++++++++++++++++++++++----- ddd-modules/sharedkernel/pom.xml | 3 ++- ddd-modules/shippingcontext/pom.xml | 3 ++- 6 files changed, 38 insertions(+), 11 deletions(-) diff --git a/ddd-modules/infrastructure/pom.xml b/ddd-modules/infrastructure/pom.xml index c301eaa92a..abf90935c3 100644 --- a/ddd-modules/infrastructure/pom.xml +++ b/ddd-modules/infrastructure/pom.xml @@ -12,8 +12,9 @@ com.baeldung.dddmodules - dddmodules + ddd-modules 1.0 + ../ diff --git a/ddd-modules/mainapp/pom.xml b/ddd-modules/mainapp/pom.xml index a048263d37..59d2ad7d3a 100644 --- a/ddd-modules/mainapp/pom.xml +++ b/ddd-modules/mainapp/pom.xml @@ -11,8 +11,9 @@ com.baeldung.dddmodules - dddmodules + ddd-modules 1.0 + ../ diff --git a/ddd-modules/ordercontext/pom.xml b/ddd-modules/ordercontext/pom.xml index abd166fb69..8dee3a5148 100644 --- a/ddd-modules/ordercontext/pom.xml +++ b/ddd-modules/ordercontext/pom.xml @@ -11,8 +11,9 @@ com.baeldung.dddmodules - dddmodules + ddd-modules 1.0 + ../ diff --git a/ddd-modules/pom.xml b/ddd-modules/pom.xml index c6dd6e1f25..6ab1829198 100644 --- a/ddd-modules/pom.xml +++ b/ddd-modules/pom.xml @@ -28,9 +28,15 @@ - junit - junit - ${junit.version} + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} test @@ -56,15 +62,31 @@ + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + 0 + + + - 3.8.1 + UTF-8 + 9 9 - UTF-8 - 3.12.2 + + 3.8.1 + 2.22.2 + 1.0 + + 5.6.2 + 3.12.2 diff --git a/ddd-modules/sharedkernel/pom.xml b/ddd-modules/sharedkernel/pom.xml index a61f03a494..1afddf1e22 100644 --- a/ddd-modules/sharedkernel/pom.xml +++ b/ddd-modules/sharedkernel/pom.xml @@ -11,8 +11,9 @@ com.baeldung.dddmodules - dddmodules + ddd-modules 1.0 + ../ diff --git a/ddd-modules/shippingcontext/pom.xml b/ddd-modules/shippingcontext/pom.xml index 2096923f90..25b5882ef1 100644 --- a/ddd-modules/shippingcontext/pom.xml +++ b/ddd-modules/shippingcontext/pom.xml @@ -11,8 +11,9 @@ com.baeldung.dddmodules - dddmodules + ddd-modules 1.0 + ../ From 88a899a283a15b022ba93915ff95e6c8d660e682 Mon Sep 17 00:00:00 2001 From: Cristian Rosu Date: Mon, 1 Jun 2020 23:32:38 +0300 Subject: [PATCH 13/46] BAEL-4070: Injecting List or Arrays from a Spring properties file --- .../lists/ListsPropertiesIntegrationTest.java | 88 +++++++++++++++++++ .../SpringListPropertiesApplication.java | 10 +++ .../src/test/resources/lists.properties | 6 ++ 3 files changed, 104 insertions(+) create mode 100644 spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesIntegrationTest.java create mode 100644 spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/SpringListPropertiesApplication.java create mode 100644 spring-boot-modules/spring-boot-properties/src/test/resources/lists.properties diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesIntegrationTest.java new file mode 100644 index 0000000000..4047e1ea95 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesIntegrationTest.java @@ -0,0 +1,88 @@ +package com.baeldung.properties.lists; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = {SpringListPropertiesApplication.class}) +public class ListsPropertiesIntegrationTest { + + @Value("${arrayOfStrings}") + private String[] arrayOfStrings; + + @Value("${arrayOfStrings}") + private List unexpectedListOfStrings; + + @Value("#{'${arrayOfStrings}'.split(',')}") + private List listOfStrings; + + @Value("#{${listOfStrings}}") + private List listOfStringsV2; + + @Value("#{'${listOfStringsWithCustomDelimiter}'.split(';')}") + private List listOfStringsWithCustomDelimiter; + + @Value("#{'${listOfBooleans}'.split(',')}") + private List listOfBooleans; + + @Value("#{'${listOfIntegers}'.split(',')}") + private List listOfIntegers; + + @Value("#{'${listOfCharacters}'.split(',')}") + private List listOfCharacters; + + @Autowired + private Environment environment; + + @Test + public void givenContextIsInitialized_ThenInjectedArrayContainsExpectedValues() { + assertEquals(arrayOfStrings, new String[] {"Baeldung", "dot", "com"}); + } + + @Test + public void givenContextIsInitialized_ThenInjectedListContainsUnexpectedValues() { + assertEquals(unexpectedListOfStrings, Collections.singletonList("Baeldung,dot,com")); + } + + @Test + public void givenContextIsInitialized_ThenInjectedListContainsExpectedValues() { + assertEquals(listOfStrings, Arrays.asList("Baeldung", "dot", "com")); + } + + @Test + public void givenContextIsInitialized_ThenInjectedListV2ContainsExpectedValues() { + assertEquals(listOfStringsV2, Arrays.asList("Baeldung", "dot", "com")); + } + + @Test + public void givenContextIsInitialized_ThenInjectedListWithCustomDelimiterContainsExpectedValues() { + assertEquals(listOfStringsWithCustomDelimiter, Arrays.asList("Baeldung", "dot", "com")); + } + + @Test + public void givenContextIsInitialized_ThenInjectedListOfBasicTypesContainsExpectedValues() { + assertEquals(listOfBooleans, Arrays.asList(false, false, true)); + assertEquals(listOfIntegers, Arrays.asList(1, 2, 3, 4)); + assertEquals(listOfCharacters, Arrays.asList('a', 'b', 'c')); + } + + @Test + public void givenContextIsInitialized_WhenReadingFromEnvironment_ThenPropertiesHaveExpectedValues() { + String[] arrayOfStrings = environment.getProperty("arrayOfStrings", String[].class); + List listOfStrings = (List)environment.getProperty("arrayOfStrings", List.class); + + assertEquals(arrayOfStrings, new String[] {"Baeldung", "dot", "com"}); + assertEquals(listOfStrings, Arrays.asList("Baeldung", "dot", "com")); + } +} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/SpringListPropertiesApplication.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/SpringListPropertiesApplication.java new file mode 100644 index 0000000000..8a66079201 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/SpringListPropertiesApplication.java @@ -0,0 +1,10 @@ +package com.baeldung.properties.lists; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +@Configuration +@PropertySource(value = "lists.properties") +public class SpringListPropertiesApplication { + +} diff --git a/spring-boot-modules/spring-boot-properties/src/test/resources/lists.properties b/spring-boot-modules/spring-boot-properties/src/test/resources/lists.properties new file mode 100644 index 0000000000..cc54d699a7 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/resources/lists.properties @@ -0,0 +1,6 @@ +arrayOfStrings=Baeldung,dot,com +listOfStrings={'Baeldung','dot','com'} +listOfStringsWithCustomDelimiter=Baeldung;dot;com +listOfBooleans=false,false,true +listOfIntegers=1,2,3,4 +listOfCharacters=a,b,c \ No newline at end of file From 5b7dde1ae8c592c12161429037f81254748ddf0b Mon Sep 17 00:00:00 2001 From: Ali Dehghani Date: Sun, 31 May 2020 23:20:10 +0430 Subject: [PATCH 14/46] Adapting the VarHandle Code to Best Practices --- .../varhandles/VariableHandlesUnitTest.java | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesUnitTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesUnitTest.java index 56e34f06a0..78a1ae3162 100644 --- a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesUnitTest.java +++ b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesUnitTest.java @@ -6,8 +6,9 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.*; -public class VariableHandlesUnitTest { +public class VariableHandlesTest { public int publicTestVariable = 1; private int privateTestVariable = 1; @@ -18,25 +19,23 @@ public class VariableHandlesUnitTest { @Test public void whenVariableHandleForPublicVariableIsCreated_ThenItIsInitializedProperly() throws NoSuchFieldException, IllegalAccessException { - VarHandle publicIntHandle = MethodHandles + VarHandle PUBLIC_TEST_VARIABLE = MethodHandles .lookup() - .in(VariableHandlesUnitTest.class) - .findVarHandle(VariableHandlesUnitTest.class, "publicTestVariable", int.class); - - assertThat(publicIntHandle.coordinateTypes().size() == 1); - assertThat(publicIntHandle.coordinateTypes().get(0) == VariableHandlesUnitTest.class); + .in(VariableHandlesTest.class) + .findVarHandle(VariableHandlesTest.class, "publicTestVariable", int.class); + assertEquals(1, PUBLIC_TEST_VARIABLE.coordinateTypes().size()); + assertEquals(VariableHandlesTest.class, PUBLIC_TEST_VARIABLE.coordinateTypes().get(0)); } @Test public void whenVariableHandleForPrivateVariableIsCreated_ThenItIsInitializedProperly() throws NoSuchFieldException, IllegalAccessException { - VarHandle privateIntHandle = MethodHandles - .privateLookupIn(VariableHandlesUnitTest.class, MethodHandles.lookup()) - .findVarHandle(VariableHandlesUnitTest.class, "privateTestVariable", int.class); - - assertThat(privateIntHandle.coordinateTypes().size() == 1); - assertThat(privateIntHandle.coordinateTypes().get(0) == VariableHandlesUnitTest.class); + VarHandle PRIVATE_TEST_VARIABLE = MethodHandles + .privateLookupIn(VariableHandlesTest.class, MethodHandles.lookup()) + .findVarHandle(VariableHandlesTest.class, "privateTestVariable", int.class); + assertEquals(1, PRIVATE_TEST_VARIABLE.coordinateTypes().size()); + assertEquals(VariableHandlesTest.class, PRIVATE_TEST_VARIABLE.coordinateTypes().get(0)); } @Test @@ -44,63 +43,64 @@ public class VariableHandlesUnitTest { VarHandle arrayVarHandle = MethodHandles .arrayElementVarHandle(int[].class); - assertThat(arrayVarHandle.coordinateTypes().size() == 2); - assertThat(arrayVarHandle.coordinateTypes().get(0) == int[].class); + assertEquals(2, arrayVarHandle.coordinateTypes().size()); + assertEquals(int[].class, arrayVarHandle.coordinateTypes().get(0)); } @Test public void givenVarHandle_whenGetIsInvoked_ThenValueOfVariableIsReturned() throws NoSuchFieldException, IllegalAccessException { - VarHandle publicIntHandle = MethodHandles + VarHandle PUBLIC_TEST_VARIABLE = MethodHandles .lookup() - .in(VariableHandlesUnitTest.class) - .findVarHandle(VariableHandlesUnitTest.class, "publicTestVariable", int.class); + .in(VariableHandlesTest.class) + .findVarHandle(VariableHandlesTest.class, "publicTestVariable", int.class); - assertThat((int) publicIntHandle.get(this) == 1); + assertEquals(1, (int) PUBLIC_TEST_VARIABLE.get(this)); } @Test public void givenVarHandle_whenSetIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException { - VarHandle publicIntHandle = MethodHandles + VarHandle VARIABLE_TO_SET = MethodHandles .lookup() - .in(VariableHandlesUnitTest.class) - .findVarHandle(VariableHandlesUnitTest.class, "variableToSet", int.class); - publicIntHandle.set(this, 15); + .in(VariableHandlesTest.class) + .findVarHandle(VariableHandlesTest.class, "variableToSet", int.class); - assertThat((int) publicIntHandle.get(this) == 15); + VARIABLE_TO_SET.set(this, 15); + assertEquals(15, (int) VARIABLE_TO_SET.get(this)); } @Test public void givenVarHandle_whenCompareAndSetIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException { - VarHandle publicIntHandle = MethodHandles + VarHandle VARIABLE_TO_COMPARE_AND_SET = MethodHandles .lookup() - .in(VariableHandlesUnitTest.class) - .findVarHandle(VariableHandlesUnitTest.class, "variableToCompareAndSet", int.class); - publicIntHandle.compareAndSet(this, 1, 100); + .in(VariableHandlesTest.class) + .findVarHandle(VariableHandlesTest.class, "variableToCompareAndSet", int.class); - assertThat((int) publicIntHandle.get(this) == 100); + VARIABLE_TO_COMPARE_AND_SET.compareAndSet(this, 1, 100); + assertEquals(100, (int) VARIABLE_TO_COMPARE_AND_SET.get(this)); } @Test public void givenVarHandle_whenGetAndAddIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException { - VarHandle publicIntHandle = MethodHandles + VarHandle VARIABLE_TO_GET_AND_ADD = MethodHandles .lookup() - .in(VariableHandlesUnitTest.class) - .findVarHandle(VariableHandlesUnitTest.class, "variableToGetAndAdd", int.class); - int before = (int) publicIntHandle.getAndAdd(this, 200); + .in(VariableHandlesTest.class) + .findVarHandle(VariableHandlesTest.class, "variableToGetAndAdd", int.class); - assertThat(before == 0); - assertThat((int) publicIntHandle.get(this) == 200); + int before = (int) VARIABLE_TO_GET_AND_ADD.getAndAdd(this, 200); + + assertEquals(0, before); + assertEquals(200, (int) VARIABLE_TO_GET_AND_ADD.get(this)); } @Test public void givenVarHandle_whenGetAndBitwiseOrIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException { - VarHandle publicIntHandle = MethodHandles + VarHandle VARIABLE_TO_BITWISE_OR = MethodHandles .lookup() - .in(VariableHandlesUnitTest.class) - .findVarHandle(VariableHandlesUnitTest.class, "variableToBitwiseOr", byte.class); - byte before = (byte) publicIntHandle.getAndBitwiseOr(this, (byte) 127); + .in(VariableHandlesTest.class) + .findVarHandle(VariableHandlesTest.class, "variableToBitwiseOr", byte.class); + byte before = (byte) VARIABLE_TO_BITWISE_OR.getAndBitwiseOr(this, (byte) 127); - assertThat(before == 0); - assertThat(variableToBitwiseOr == 127); + assertEquals(0, before); + assertEquals(127, (byte) VARIABLE_TO_BITWISE_OR.get(this)); } } From 756f70b29f1de78ce0f8af5761a1b7819b18d6bf Mon Sep 17 00:00:00 2001 From: Ali Dehghani Date: Tue, 2 Jun 2020 21:07:48 +0430 Subject: [PATCH 15/46] Rename the Class --- .../varhandles/VariableHandlesUnitTest.java | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesUnitTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesUnitTest.java index 78a1ae3162..a7263f0bb2 100644 --- a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesUnitTest.java +++ b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesUnitTest.java @@ -5,10 +5,9 @@ import org.junit.Test; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; -public class VariableHandlesTest { +public class VariableHandlesUnitTest { public int publicTestVariable = 1; private int privateTestVariable = 1; @@ -21,21 +20,21 @@ public class VariableHandlesTest { public void whenVariableHandleForPublicVariableIsCreated_ThenItIsInitializedProperly() throws NoSuchFieldException, IllegalAccessException { VarHandle PUBLIC_TEST_VARIABLE = MethodHandles .lookup() - .in(VariableHandlesTest.class) - .findVarHandle(VariableHandlesTest.class, "publicTestVariable", int.class); + .in(VariableHandlesUnitTest.class) + .findVarHandle(VariableHandlesUnitTest.class, "publicTestVariable", int.class); assertEquals(1, PUBLIC_TEST_VARIABLE.coordinateTypes().size()); - assertEquals(VariableHandlesTest.class, PUBLIC_TEST_VARIABLE.coordinateTypes().get(0)); + assertEquals(VariableHandlesUnitTest.class, PUBLIC_TEST_VARIABLE.coordinateTypes().get(0)); } @Test public void whenVariableHandleForPrivateVariableIsCreated_ThenItIsInitializedProperly() throws NoSuchFieldException, IllegalAccessException { VarHandle PRIVATE_TEST_VARIABLE = MethodHandles - .privateLookupIn(VariableHandlesTest.class, MethodHandles.lookup()) - .findVarHandle(VariableHandlesTest.class, "privateTestVariable", int.class); + .privateLookupIn(VariableHandlesUnitTest.class, MethodHandles.lookup()) + .findVarHandle(VariableHandlesUnitTest.class, "privateTestVariable", int.class); assertEquals(1, PRIVATE_TEST_VARIABLE.coordinateTypes().size()); - assertEquals(VariableHandlesTest.class, PRIVATE_TEST_VARIABLE.coordinateTypes().get(0)); + assertEquals(VariableHandlesUnitTest.class, PRIVATE_TEST_VARIABLE.coordinateTypes().get(0)); } @Test @@ -51,8 +50,8 @@ public class VariableHandlesTest { public void givenVarHandle_whenGetIsInvoked_ThenValueOfVariableIsReturned() throws NoSuchFieldException, IllegalAccessException { VarHandle PUBLIC_TEST_VARIABLE = MethodHandles .lookup() - .in(VariableHandlesTest.class) - .findVarHandle(VariableHandlesTest.class, "publicTestVariable", int.class); + .in(VariableHandlesUnitTest.class) + .findVarHandle(VariableHandlesUnitTest.class, "publicTestVariable", int.class); assertEquals(1, (int) PUBLIC_TEST_VARIABLE.get(this)); } @@ -61,8 +60,8 @@ public class VariableHandlesTest { public void givenVarHandle_whenSetIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException { VarHandle VARIABLE_TO_SET = MethodHandles .lookup() - .in(VariableHandlesTest.class) - .findVarHandle(VariableHandlesTest.class, "variableToSet", int.class); + .in(VariableHandlesUnitTest.class) + .findVarHandle(VariableHandlesUnitTest.class, "variableToSet", int.class); VARIABLE_TO_SET.set(this, 15); assertEquals(15, (int) VARIABLE_TO_SET.get(this)); @@ -72,8 +71,8 @@ public class VariableHandlesTest { public void givenVarHandle_whenCompareAndSetIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException { VarHandle VARIABLE_TO_COMPARE_AND_SET = MethodHandles .lookup() - .in(VariableHandlesTest.class) - .findVarHandle(VariableHandlesTest.class, "variableToCompareAndSet", int.class); + .in(VariableHandlesUnitTest.class) + .findVarHandle(VariableHandlesUnitTest.class, "variableToCompareAndSet", int.class); VARIABLE_TO_COMPARE_AND_SET.compareAndSet(this, 1, 100); assertEquals(100, (int) VARIABLE_TO_COMPARE_AND_SET.get(this)); @@ -83,8 +82,8 @@ public class VariableHandlesTest { public void givenVarHandle_whenGetAndAddIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException { VarHandle VARIABLE_TO_GET_AND_ADD = MethodHandles .lookup() - .in(VariableHandlesTest.class) - .findVarHandle(VariableHandlesTest.class, "variableToGetAndAdd", int.class); + .in(VariableHandlesUnitTest.class) + .findVarHandle(VariableHandlesUnitTest.class, "variableToGetAndAdd", int.class); int before = (int) VARIABLE_TO_GET_AND_ADD.getAndAdd(this, 200); @@ -96,8 +95,8 @@ public class VariableHandlesTest { public void givenVarHandle_whenGetAndBitwiseOrIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException { VarHandle VARIABLE_TO_BITWISE_OR = MethodHandles .lookup() - .in(VariableHandlesTest.class) - .findVarHandle(VariableHandlesTest.class, "variableToBitwiseOr", byte.class); + .in(VariableHandlesUnitTest.class) + .findVarHandle(VariableHandlesUnitTest.class, "variableToBitwiseOr", byte.class); byte before = (byte) VARIABLE_TO_BITWISE_OR.getAndBitwiseOr(this, (byte) 127); assertEquals(0, before); From be292ec3f22c4ca82e7154718d89595c9cd1c9c6 Mon Sep 17 00:00:00 2001 From: Ali Dehghani Date: Tue, 2 Jun 2020 21:32:45 +0430 Subject: [PATCH 16/46] Avoid Using newInstance on Class --- .../reflection/java/reflection/ReflectionUnitTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/java/reflection/ReflectionUnitTest.java b/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/java/reflection/ReflectionUnitTest.java index 0c090901e7..a791d64874 100644 --- a/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/java/reflection/ReflectionUnitTest.java +++ b/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/java/reflection/ReflectionUnitTest.java @@ -200,7 +200,7 @@ public class ReflectionUnitTest { @Test public void givenClassField_whenSetsAndGetsValue_thenCorrect() throws Exception { final Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); - final Bird bird = (Bird) birdClass.newInstance(); + final Bird bird = (Bird) birdClass.getConstructor().newInstance(); final Field field = birdClass.getDeclaredField("walks"); field.setAccessible(true); @@ -266,7 +266,7 @@ public class ReflectionUnitTest { @Test public void givenMethod_whenInvokes_thenCorrect() throws Exception { final Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); - final Bird bird = (Bird) birdClass.newInstance(); + final Bird bird = (Bird) birdClass.getConstructor().newInstance(); final Method setWalksMethod = birdClass.getDeclaredMethod("setWalks", boolean.class); final Method walksMethod = birdClass.getDeclaredMethod("walks"); final boolean walks = (boolean) walksMethod.invoke(bird); From 89ea700e24631a695118e02ecf1e4ef831a00a08 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Tue, 2 Jun 2020 22:55:10 +0530 Subject: [PATCH 17/46] JAVA-39: Removed module spring-security-kerberos --- .../spring-security-kerberos/README.md | 13 --- .../spring-security-kerberos/pom.xml | 69 --------------- .../main/java/com/baeldung/Application.java | 13 --- .../baeldung/config/WebSecurityConfig.java | 87 ------------------- .../security/DummyUserDetailsService.java | 16 ---- 5 files changed, 198 deletions(-) delete mode 100644 spring-security-modules/spring-security-kerberos/README.md delete mode 100644 spring-security-modules/spring-security-kerberos/pom.xml delete mode 100644 spring-security-modules/spring-security-kerberos/src/main/java/com/baeldung/Application.java delete mode 100644 spring-security-modules/spring-security-kerberos/src/main/java/com/baeldung/config/WebSecurityConfig.java delete mode 100644 spring-security-modules/spring-security-kerberos/src/main/java/com/baeldung/security/DummyUserDetailsService.java diff --git a/spring-security-modules/spring-security-kerberos/README.md b/spring-security-modules/spring-security-kerberos/README.md deleted file mode 100644 index a868fb86b7..0000000000 --- a/spring-security-modules/spring-security-kerberos/README.md +++ /dev/null @@ -1,13 +0,0 @@ -## Spring Security Kerberos - -This module contains articles about Spring Security Kerberos - -### Relevant Articles: - -- [Introduction to SPNEGO/Kerberos Authentication in Spring](https://www.baeldung.com/spring-security-kerberos) - -### @PreFilter and @PostFilter annotations - -### Build the Project ### - -`mvn clean install` \ No newline at end of file diff --git a/spring-security-modules/spring-security-kerberos/pom.xml b/spring-security-modules/spring-security-kerberos/pom.xml deleted file mode 100644 index 51a48a78c6..0000000000 --- a/spring-security-modules/spring-security-kerberos/pom.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - 4.0.0 - spring-security-kerberos - 0.1-SNAPSHOT - spring-security-kerberos - war - - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-security - - - - org.springframework.security.kerberos - spring-security-kerberos-core - ${spring-security-kerberos.version} - - - org.springframework.security.kerberos - spring-security-kerberos-web - ${spring-security-kerberos.version} - - - org.springframework.security.kerberos - spring-security-kerberos-client - ${spring-security-kerberos.version} - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.security - spring-security-test - test - - - - - - - org.apache.maven.plugins - maven-war-plugin - - - - - - 1.0.1.RELEASE - - - diff --git a/spring-security-modules/spring-security-kerberos/src/main/java/com/baeldung/Application.java b/spring-security-modules/spring-security-kerberos/src/main/java/com/baeldung/Application.java deleted file mode 100644 index 37dbe7dab8..0000000000 --- a/spring-security-modules/spring-security-kerberos/src/main/java/com/baeldung/Application.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class Application { - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } - -} diff --git a/spring-security-modules/spring-security-kerberos/src/main/java/com/baeldung/config/WebSecurityConfig.java b/spring-security-modules/spring-security-kerberos/src/main/java/com/baeldung/config/WebSecurityConfig.java deleted file mode 100644 index c1c206e5c9..0000000000 --- a/spring-security-modules/spring-security-kerberos/src/main/java/com/baeldung/config/WebSecurityConfig.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.baeldung.config; - -import com.baeldung.security.DummyUserDetailsService; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.FileSystemResource; -import org.springframework.security.authentication.AuthenticationManager; -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.WebSecurityConfigurerAdapter; -import org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider; -import org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider; -import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient; -import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator; -import org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter; -import org.springframework.security.kerberos.web.authentication.SpnegoEntryPoint; -import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; - -@Configuration -public class WebSecurityConfig extends WebSecurityConfigurerAdapter { - - @Override - protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests() - .anyRequest() - .authenticated() - .and() - .addFilterBefore(spnegoAuthenticationProcessingFilter(authenticationManagerBean()), BasicAuthenticationFilter.class); - } - - @Override - @Bean - public AuthenticationManager authenticationManagerBean() throws Exception { - return super.authenticationManagerBean(); - } - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.authenticationProvider(kerberosAuthenticationProvider()) - .authenticationProvider(kerberosServiceAuthenticationProvider()); - } - - @Bean - public KerberosAuthenticationProvider kerberosAuthenticationProvider() { - KerberosAuthenticationProvider provider = new KerberosAuthenticationProvider(); - SunJaasKerberosClient client = new SunJaasKerberosClient(); - client.setDebug(true); - provider.setKerberosClient(client); - provider.setUserDetailsService(dummyUserDetailsService()); - return provider; - } - - @Bean - public SpnegoEntryPoint spnegoEntryPoint() { - return new SpnegoEntryPoint("/login"); - } - - @Bean - public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter(AuthenticationManager authenticationManager) { - SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter(); - filter.setAuthenticationManager(authenticationManager); - return filter; - } - - @Bean - public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() { - KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider(); - provider.setTicketValidator(sunJaasKerberosTicketValidator()); - provider.setUserDetailsService(dummyUserDetailsService()); - return provider; - } - - @Bean - public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() { - SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator(); - ticketValidator.setServicePrincipal("HTTP/demo.kerberos.bealdung.com@baeldung.com"); - ticketValidator.setKeyTabLocation(new FileSystemResource("baeldung.keytab")); - ticketValidator.setDebug(true); - return ticketValidator; - } - - @Bean - public DummyUserDetailsService dummyUserDetailsService() { - return new DummyUserDetailsService(); - } - -} \ No newline at end of file diff --git a/spring-security-modules/spring-security-kerberos/src/main/java/com/baeldung/security/DummyUserDetailsService.java b/spring-security-modules/spring-security-kerberos/src/main/java/com/baeldung/security/DummyUserDetailsService.java deleted file mode 100644 index 6ddd6c8969..0000000000 --- a/spring-security-modules/spring-security-kerberos/src/main/java/com/baeldung/security/DummyUserDetailsService.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung.security; - -import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; - -public class DummyUserDetailsService implements UserDetailsService { - - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - return new User(username, "notUsed", true, true, true, true, AuthorityUtils.createAuthorityList("ROLE_USER")); - } - -} \ No newline at end of file From 97fa800bbdb54d81923fc224cac4c312ad808f88 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Tue, 2 Jun 2020 22:56:31 +0530 Subject: [PATCH 18/46] JAVA-39: Moved article from spring-security kerberos module to spring-security-sso/spring-security-sso-kerberos --- .../spring-security-sso-kerberos/README.md | 1 + .../java/com/baeldung/intro/Application.java | 13 +++ .../intro/config/WebSecurityConfig.java | 88 +++++++++++++++++++ .../security/DummyUserDetailsService.java | 16 ++++ 4 files changed, 118 insertions(+) create mode 100644 spring-security-modules/spring-security-sso/spring-security-sso-kerberos/src/main/java/com/baeldung/intro/Application.java create mode 100644 spring-security-modules/spring-security-sso/spring-security-sso-kerberos/src/main/java/com/baeldung/intro/config/WebSecurityConfig.java create mode 100644 spring-security-modules/spring-security-sso/spring-security-sso-kerberos/src/main/java/com/baeldung/intro/security/DummyUserDetailsService.java diff --git a/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/README.md b/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/README.md index 3aa092edb8..4bb0eea16c 100644 --- a/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/README.md +++ b/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/README.md @@ -1,3 +1,4 @@ ## Relevant articles: - [Spring Security Kerberos Integration](https://www.baeldung.com/spring-security-kerberos-integration) +- [Introduction to SPNEGO/Kerberos Authentication in Spring](https://www.baeldung.com/spring-security-kerberos) diff --git a/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/src/main/java/com/baeldung/intro/Application.java b/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/src/main/java/com/baeldung/intro/Application.java new file mode 100644 index 0000000000..2cddbf0f22 --- /dev/null +++ b/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/src/main/java/com/baeldung/intro/Application.java @@ -0,0 +1,13 @@ +package com.baeldung.intro; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/src/main/java/com/baeldung/intro/config/WebSecurityConfig.java b/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/src/main/java/com/baeldung/intro/config/WebSecurityConfig.java new file mode 100644 index 0000000000..cc694a3b83 --- /dev/null +++ b/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/src/main/java/com/baeldung/intro/config/WebSecurityConfig.java @@ -0,0 +1,88 @@ +package com.baeldung.intro.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.FileSystemResource; +import org.springframework.security.authentication.AuthenticationManager; +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.WebSecurityConfigurerAdapter; +import org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider; +import org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider; +import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient; +import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator; +import org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter; +import org.springframework.security.kerberos.web.authentication.SpnegoEntryPoint; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; + +import com.baeldung.intro.security.DummyUserDetailsService; + +@Configuration +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + .anyRequest() + .authenticated() + .and() + .addFilterBefore(spnegoAuthenticationProcessingFilter(authenticationManagerBean()), BasicAuthenticationFilter.class); + } + + @Override + @Bean + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.authenticationProvider(kerberosAuthenticationProvider()) + .authenticationProvider(kerberosServiceAuthenticationProvider()); + } + + @Bean + public KerberosAuthenticationProvider kerberosAuthenticationProvider() { + KerberosAuthenticationProvider provider = new KerberosAuthenticationProvider(); + SunJaasKerberosClient client = new SunJaasKerberosClient(); + client.setDebug(true); + provider.setKerberosClient(client); + provider.setUserDetailsService(dummyUserDetailsService()); + return provider; + } + + @Bean + public SpnegoEntryPoint spnegoEntryPoint() { + return new SpnegoEntryPoint("/login"); + } + + @Bean + public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter(AuthenticationManager authenticationManager) { + SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter(); + filter.setAuthenticationManager(authenticationManager); + return filter; + } + + @Bean + public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() { + KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider(); + provider.setTicketValidator(sunJaasKerberosTicketValidator()); + provider.setUserDetailsService(dummyUserDetailsService()); + return provider; + } + + @Bean + public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() { + SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator(); + ticketValidator.setServicePrincipal("HTTP/demo.kerberos.bealdung.com@baeldung.com"); + ticketValidator.setKeyTabLocation(new FileSystemResource("baeldung.keytab")); + ticketValidator.setDebug(true); + return ticketValidator; + } + + @Bean + public DummyUserDetailsService dummyUserDetailsService() { + return new DummyUserDetailsService(); + } + +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/src/main/java/com/baeldung/intro/security/DummyUserDetailsService.java b/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/src/main/java/com/baeldung/intro/security/DummyUserDetailsService.java new file mode 100644 index 0000000000..f564c9f756 --- /dev/null +++ b/spring-security-modules/spring-security-sso/spring-security-sso-kerberos/src/main/java/com/baeldung/intro/security/DummyUserDetailsService.java @@ -0,0 +1,16 @@ +package com.baeldung.intro.security; + +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +public class DummyUserDetailsService implements UserDetailsService { + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + return new User(username, "notUsed", true, true, true, true, AuthorityUtils.createAuthorityList("ROLE_USER")); + } + +} \ No newline at end of file From d214da3cb1deeba6a17d48973605cf25da8392d2 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Tue, 2 Jun 2020 22:57:22 +0530 Subject: [PATCH 19/46] JAVA-39: Updated parent module pom to remove deleted module --- spring-security-modules/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-security-modules/pom.xml b/spring-security-modules/pom.xml index 60a662781f..954b9335e4 100644 --- a/spring-security-modules/pom.xml +++ b/spring-security-modules/pom.xml @@ -20,7 +20,6 @@ spring-security-cache-control spring-security-core spring-security-cors - spring-security-kerberos spring-security-mvc spring-security-mvc-boot-1 spring-security-mvc-boot-2 From b07bcce7efcdf939dd336b2dceabbb88449b89b9 Mon Sep 17 00:00:00 2001 From: Ali Dehghani Date: Tue, 2 Jun 2020 22:03:54 +0430 Subject: [PATCH 20/46] Introducing Integer Cache --- .../stringtoint/StringToIntOrIntegerUnitTest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core-java-modules/core-java-string-conversions/src/test/java/com/baeldung/stringtoint/StringToIntOrIntegerUnitTest.java b/core-java-modules/core-java-string-conversions/src/test/java/com/baeldung/stringtoint/StringToIntOrIntegerUnitTest.java index 106f1fc974..336b2ac324 100644 --- a/core-java-modules/core-java-string-conversions/src/test/java/com/baeldung/stringtoint/StringToIntOrIntegerUnitTest.java +++ b/core-java-modules/core-java-string-conversions/src/test/java/com/baeldung/stringtoint/StringToIntOrIntegerUnitTest.java @@ -26,6 +26,17 @@ public class StringToIntOrIntegerUnitTest { assertThat(result).isEqualTo(new Integer(42)); } + @Test + public void givenString_whenCallingValueOf_shouldCacheSomeValues() { + for (int i = -128; i <= 127; i++) { + String value = i + ""; + Integer first = Integer.valueOf(value); + Integer second = Integer.valueOf(value); + + assertThat(first).isSameAs(second); + } + } + @Test public void givenString_whenCallingIntegerConstructor_shouldConvertToInt() { String givenString = "42"; From dd5e1190fa445295e61b46d35f9fdf5f9b8e56ce Mon Sep 17 00:00:00 2001 From: Cristian Rosu Date: Tue, 2 Jun 2020 22:53:54 +0300 Subject: [PATCH 21/46] BAEL-4070: updated test names to match Baeldung's guidelines + makred test as Unit Test instead of Integration Test --- ...ionTest.java => ListsPropertiesUnitTest.java} | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) rename spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/{ListsPropertiesIntegrationTest.java => ListsPropertiesUnitTest.java} (79%) diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java similarity index 79% rename from spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesIntegrationTest.java rename to spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java index 4047e1ea95..8c1835a0a9 100644 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesIntegrationTest.java +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java @@ -16,7 +16,7 @@ import static org.junit.Assert.assertEquals; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {SpringListPropertiesApplication.class}) -public class ListsPropertiesIntegrationTest { +public class ListsPropertiesUnitTest { @Value("${arrayOfStrings}") private String[] arrayOfStrings; @@ -46,39 +46,39 @@ public class ListsPropertiesIntegrationTest { private Environment environment; @Test - public void givenContextIsInitialized_ThenInjectedArrayContainsExpectedValues() { + public void whenContextIsInitialized_ThenInjectedArrayContainsExpectedValues() { assertEquals(arrayOfStrings, new String[] {"Baeldung", "dot", "com"}); } @Test - public void givenContextIsInitialized_ThenInjectedListContainsUnexpectedValues() { + public void whenContextIsInitialized_ThenInjectedListContainsUnexpectedValues() { assertEquals(unexpectedListOfStrings, Collections.singletonList("Baeldung,dot,com")); } @Test - public void givenContextIsInitialized_ThenInjectedListContainsExpectedValues() { + public void whenContextIsInitialized_ThenInjectedListContainsExpectedValues() { assertEquals(listOfStrings, Arrays.asList("Baeldung", "dot", "com")); } @Test - public void givenContextIsInitialized_ThenInjectedListV2ContainsExpectedValues() { + public void whenContextIsInitialized_ThenInjectedListV2ContainsExpectedValues() { assertEquals(listOfStringsV2, Arrays.asList("Baeldung", "dot", "com")); } @Test - public void givenContextIsInitialized_ThenInjectedListWithCustomDelimiterContainsExpectedValues() { + public void whenContextIsInitialized_ThenInjectedListWithCustomDelimiterContainsExpectedValues() { assertEquals(listOfStringsWithCustomDelimiter, Arrays.asList("Baeldung", "dot", "com")); } @Test - public void givenContextIsInitialized_ThenInjectedListOfBasicTypesContainsExpectedValues() { + public void whenContextIsInitialized_ThenInjectedListOfBasicTypesContainsExpectedValues() { assertEquals(listOfBooleans, Arrays.asList(false, false, true)); assertEquals(listOfIntegers, Arrays.asList(1, 2, 3, 4)); assertEquals(listOfCharacters, Arrays.asList('a', 'b', 'c')); } @Test - public void givenContextIsInitialized_WhenReadingFromEnvironment_ThenPropertiesHaveExpectedValues() { + public void WhenReadingFromSpringEnvironment_ThenPropertiesHaveExpectedValues() { String[] arrayOfStrings = environment.getProperty("arrayOfStrings", String[].class); List listOfStrings = (List)environment.getProperty("arrayOfStrings", List.class); From f0befa0f8b9d263dfc167b1eac30389c7ca04898 Mon Sep 17 00:00:00 2001 From: Krzysztof Woyke Date: Wed, 3 Jun 2020 09:00:03 +0200 Subject: [PATCH 22/46] JAVA-1644: Remove overriden spring-boot.version property --- persistence-modules/spring-boot-persistence/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/persistence-modules/spring-boot-persistence/pom.xml b/persistence-modules/spring-boot-persistence/pom.xml index c58e8dbf86..cc26ff58d5 100644 --- a/persistence-modules/spring-boot-persistence/pom.xml +++ b/persistence-modules/spring-boot-persistence/pom.xml @@ -77,7 +77,6 @@ UTF-8 2.23.0 2.0.1.Final - 2.1.7.RELEASE From 829140d488d33795b1c5b674cc4865f116391ba4 Mon Sep 17 00:00:00 2001 From: Ali Dehghani Date: Wed, 3 Jun 2020 14:10:58 +0430 Subject: [PATCH 23/46] Polluting the Heap --- .../varargs/HeapPollutionUnitTest.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/varargs/HeapPollutionUnitTest.java diff --git a/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/varargs/HeapPollutionUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/varargs/HeapPollutionUnitTest.java new file mode 100644 index 0000000000..ced2c00bea --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/varargs/HeapPollutionUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.varargs; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class HeapPollutionUnitTest { + + @Test(expected = ClassCastException.class) + public void givenGenericVararg_whenUsedUnsafe_shouldThrowClassCastException() { + String one = firstOfFirst(Arrays.asList("one", "two"), Collections.emptyList()); + + assertEquals("one", one); + } + + @Test(expected = ClassCastException.class) + public void givenGenericVararg_whenRefEscapes_mayCauseSubtleBugs() { + String[] args = returnAsIs("One", "Two"); + } + + private static String firstOfFirst(List... strings) { + List ints = Collections.singletonList(42); + Object[] objects = strings; + objects[0] = ints; + + return strings[0].get(0); + } + + private static T[] toArray(T... arguments) { + return arguments; + } + + private static T[] returnAsIs(T a, T b) { + return toArray(a, b); + } +} From bc2c23ae9e229be2ba0c05d2784a6a86aea50c52 Mon Sep 17 00:00:00 2001 From: Cristian Rosu Date: Thu, 4 Jun 2020 12:18:03 +0300 Subject: [PATCH 24/46] BAEL-4070: removed unnecessary curly brace, fixed test name --- .../baeldung/properties/lists/ListsPropertiesUnitTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java index 8c1835a0a9..80cb8e9ea0 100644 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java @@ -15,7 +15,7 @@ import java.util.List; import static org.junit.Assert.assertEquals; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = {SpringListPropertiesApplication.class}) +@ContextConfiguration(classes = SpringListPropertiesApplication.class) public class ListsPropertiesUnitTest { @Value("${arrayOfStrings}") @@ -78,7 +78,7 @@ public class ListsPropertiesUnitTest { } @Test - public void WhenReadingFromSpringEnvironment_ThenPropertiesHaveExpectedValues() { + public void whenReadingFromSpringEnvironment_ThenPropertiesHaveExpectedValues() { String[] arrayOfStrings = environment.getProperty("arrayOfStrings", String[].class); List listOfStrings = (List)environment.getProperty("arrayOfStrings", List.class); From 829b4975c4cd6269fd6744d8b5b800efe7559470 Mon Sep 17 00:00:00 2001 From: Josh Cummings Date: Thu, 4 Jun 2020 10:06:16 -0600 Subject: [PATCH 25/46] Update README.md Issue BAEL-3896 --- spring-rest-http/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-rest-http/README.md b/spring-rest-http/README.md index 35793cb281..f78f8784b0 100644 --- a/spring-rest-http/README.md +++ b/spring-rest-http/README.md @@ -13,3 +13,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring RequestMapping](https://www.baeldung.com/spring-requestmapping) - [Guide to DeferredResult in Spring](https://www.baeldung.com/spring-deferred-result) - [Using JSON Patch in Spring REST APIs](https://www.baeldung.com/spring-rest-json-patch) +- [Using OpenAPI and JSON Request Parameters](https://www.baeldung.com/openapi-json-query-parameters) From 07751eeea2af16605d98ecf2bed47ed2ac0cf230 Mon Sep 17 00:00:00 2001 From: Krzysztof Woyke Date: Fri, 5 Jun 2020 15:10:58 +0200 Subject: [PATCH 26/46] JAVA-1782: Add byte-buddy to parent-boot-2 --- parent-boot-2/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/parent-boot-2/pom.xml b/parent-boot-2/pom.xml index c7bb11b1d5..631d8a0581 100644 --- a/parent-boot-2/pom.xml +++ b/parent-boot-2/pom.xml @@ -32,6 +32,11 @@ io.rest-assured rest-assured + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + org.springframework.boot spring-boot-starter-test From b8a3dd7a687fb7e8c6a751aa9a214e4f84bbf99f Mon Sep 17 00:00:00 2001 From: Krzysztof Woyke Date: Fri, 5 Jun 2020 15:38:09 +0200 Subject: [PATCH 27/46] JAVA-1782: Remove byte-buddy dep from parent-boot-2's children --- persistence-modules/spring-boot-persistence-h2/pom.xml | 5 ----- spring-5-mvc/pom.xml | 5 ----- spring-boot-groovy/pom.xml | 5 ----- spring-boot-modules/spring-boot-keycloak/pom.xml | 4 ---- spring-boot-rest/pom.xml | 5 ----- spring-jinq/pom.xml | 7 ------- spring-rest-hal-browser/pom.xml | 6 ------ spring-security-modules/spring-security-mvc-boot-1/pom.xml | 4 ---- spring-social-login/pom.xml | 7 ------- 9 files changed, 48 deletions(-) diff --git a/persistence-modules/spring-boot-persistence-h2/pom.xml b/persistence-modules/spring-boot-persistence-h2/pom.xml index 7070b5e674..9e6c780931 100644 --- a/persistence-modules/spring-boot-persistence-h2/pom.xml +++ b/persistence-modules/spring-boot-persistence-h2/pom.xml @@ -40,11 +40,6 @@ db-util ${db-util.version} - - net.bytebuddy - byte-buddy - ${byte-buddy.version} - diff --git a/spring-5-mvc/pom.xml b/spring-5-mvc/pom.xml index 4b42528d0f..945ddef5e1 100644 --- a/spring-5-mvc/pom.xml +++ b/spring-5-mvc/pom.xml @@ -42,11 +42,6 @@ org.slf4j jcl-over-slf4j - - net.bytebuddy - byte-buddy - ${byte-buddy.version} - org.jetbrains.kotlin diff --git a/spring-boot-groovy/pom.xml b/spring-boot-groovy/pom.xml index f61398c5d6..9ea8d7b2a9 100644 --- a/spring-boot-groovy/pom.xml +++ b/spring-boot-groovy/pom.xml @@ -41,11 +41,6 @@ h2 runtime - - net.bytebuddy - byte-buddy-dep - 1.10.9 - diff --git a/spring-boot-modules/spring-boot-keycloak/pom.xml b/spring-boot-modules/spring-boot-keycloak/pom.xml index 8e917df2b7..68d4ec4b8f 100644 --- a/spring-boot-modules/spring-boot-keycloak/pom.xml +++ b/spring-boot-modules/spring-boot-keycloak/pom.xml @@ -41,10 +41,6 @@ org.springframework.boot spring-boot-starter-data-jpa - - net.bytebuddy - byte-buddy - org.springframework.boot diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index a8500d50f2..10dacf99e8 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -79,11 +79,6 @@ modelmapper ${modelmapper.version} - - net.bytebuddy - byte-buddy - ${byte-buddy.version} - diff --git a/spring-jinq/pom.xml b/spring-jinq/pom.xml index 073808823c..647c0907a7 100644 --- a/spring-jinq/pom.xml +++ b/spring-jinq/pom.xml @@ -37,12 +37,6 @@ spring-boot-starter-data-jpa - - net.bytebuddy - byte-buddy-dep - ${bytebuddy.version} - - org.springframework @@ -73,7 +67,6 @@ 1.8.29 - 1.10.10 diff --git a/spring-rest-hal-browser/pom.xml b/spring-rest-hal-browser/pom.xml index 32a0b52875..7b629dba44 100644 --- a/spring-rest-hal-browser/pom.xml +++ b/spring-rest-hal-browser/pom.xml @@ -35,11 +35,6 @@ com.h2database h2 - - net.bytebuddy - byte-buddy-dep - ${bytebuddy.version} - @@ -56,7 +51,6 @@ - 1.10.10 1.8 1.8 diff --git a/spring-security-modules/spring-security-mvc-boot-1/pom.xml b/spring-security-modules/spring-security-mvc-boot-1/pom.xml index b00b7bab32..7ad18376ec 100644 --- a/spring-security-modules/spring-security-mvc-boot-1/pom.xml +++ b/spring-security-modules/spring-security-mvc-boot-1/pom.xml @@ -106,10 +106,6 @@ ${ehcache-core.version} jar - - net.bytebuddy - byte-buddy - diff --git a/spring-social-login/pom.xml b/spring-social-login/pom.xml index 628f439cc0..0de20cd087 100644 --- a/spring-social-login/pom.xml +++ b/spring-social-login/pom.xml @@ -62,12 +62,6 @@ h2 - - net.bytebuddy - byte-buddy-dep - ${bytebuddy.version} - - @@ -102,7 +96,6 @@ - 1.10.9 2.0.3.RELEASE From de8acfd6e02afec5e466823b73865caab01c6f88 Mon Sep 17 00:00:00 2001 From: Chirag Dewan Date: Sun, 7 Jun 2020 15:29:59 +0530 Subject: [PATCH 28/46] BAEL3889 - Adding braces in EvenOddPartitioner --- .../java/com/baeldung/kafka/producer/EvenOddPartitioner.java | 5 +++-- .../main/java/com/baeldung/kafka/producer/KafkaProducer.java | 2 +- .../com/baeldung/kafka/producer/KafkaProducerUnitTest.java | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries-data-2/src/main/java/com/baeldung/kafka/producer/EvenOddPartitioner.java b/libraries-data-2/src/main/java/com/baeldung/kafka/producer/EvenOddPartitioner.java index 12c86828dd..1c77226037 100644 --- a/libraries-data-2/src/main/java/com/baeldung/kafka/producer/EvenOddPartitioner.java +++ b/libraries-data-2/src/main/java/com/baeldung/kafka/producer/EvenOddPartitioner.java @@ -1,4 +1,4 @@ -package com.baeldung.kafka; +package com.baeldung.kafka.producer; import org.apache.kafka.clients.producer.internals.DefaultPartitioner; import org.apache.kafka.common.Cluster; @@ -8,8 +8,9 @@ public class EvenOddPartitioner extends DefaultPartitioner { @Override public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) { - if (((String)key).length() % 2 == 0) + if (((String) key).length() % 2 == 0) { return 0; + } return 1; } diff --git a/libraries-data-2/src/main/java/com/baeldung/kafka/producer/KafkaProducer.java b/libraries-data-2/src/main/java/com/baeldung/kafka/producer/KafkaProducer.java index 8574cd1c40..911c9ed3d7 100644 --- a/libraries-data-2/src/main/java/com/baeldung/kafka/producer/KafkaProducer.java +++ b/libraries-data-2/src/main/java/com/baeldung/kafka/producer/KafkaProducer.java @@ -1,4 +1,4 @@ -package com.baeldung.kafka; +package com.baeldung.kafka.producer; import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.ProducerRecord; diff --git a/libraries-data-2/src/test/java/com/baeldung/kafka/producer/KafkaProducerUnitTest.java b/libraries-data-2/src/test/java/com/baeldung/kafka/producer/KafkaProducerUnitTest.java index ce3803322c..a7156ed886 100644 --- a/libraries-data-2/src/test/java/com/baeldung/kafka/producer/KafkaProducerUnitTest.java +++ b/libraries-data-2/src/test/java/com/baeldung/kafka/producer/KafkaProducerUnitTest.java @@ -1,5 +1,7 @@ -package com.baeldung.kafka; +package com.baeldung.kafka.producer; +import com.baeldung.kafka.producer.EvenOddPartitioner; +import com.baeldung.kafka.producer.KafkaProducer; import org.apache.kafka.clients.producer.MockProducer; import org.apache.kafka.clients.producer.RecordMetadata; import org.apache.kafka.common.Cluster; From 6f21d2eb744f49decc035abd12bf25835b7a2f7e Mon Sep 17 00:00:00 2001 From: mikr Date: Sun, 7 Jun 2020 12:13:32 +0200 Subject: [PATCH 29/46] JAVA-1749 Update UUID article and code --- .../java/com/baeldung/uuid/UUIDGenerator.java | 134 ++++++++++++------ .../baeldung/uuid/UUIDGeneratorUnitTest.java | 64 +++++++++ 2 files changed, 156 insertions(+), 42 deletions(-) create mode 100644 core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java index 2659b29491..cb43a26929 100644 --- a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java @@ -3,30 +3,57 @@ package com.baeldung.uuid; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.Arrays; +import java.util.Random; import java.util.UUID; public class UUIDGenerator { - /** - * These are predefined UUID for name spaces - */ - private static final String NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8"; - private static final String NAMESPACE_URL = "6ba7b811-9dad-11d1-80b4-00c04fd430c8"; - private static final String NAMESPACE_OID = "6ba7b812-9dad-11d1-80b4-00c04fd430c8"; - private static final String NAMESPACE_X500 = "6ba7b814-9dad-11d1-80b4-00c04fd430c8"; - private static final char[] hexArray = "0123456789ABCDEF".toCharArray(); - public static void main(String[] args) { - try { - System.out.println("Type 3 : " + generateType3UUID(NAMESPACE_DNS, "google.com")); - System.out.println("Type 4 : " + generateType4UUID()); - System.out.println("Type 5 : " + generateType5UUID(NAMESPACE_URL, "google.com")); - System.out.println("Unique key : " + generateUniqueKeysWithUUIDAndMessageDigest()); - } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { - e.printStackTrace(); - } + /** + * Type 1 UUID Generation + */ + public static UUID generateType1UUID() { + + long most64SigBits = get64MostSignificantBitsForVersion1(); + long least64SigBits = get64LeastSignificantBitsForVersion1(); + + return new UUID(most64SigBits, least64SigBits); + } + + private static long get64LeastSignificantBitsForVersion1() { + Random random = new Random(); + long random63BitLong = random.nextLong() & 0x3FFFFFFFFFFFFFFFL; + long variant3BitFlag = 0x8000000000000000L; + return random63BitLong + variant3BitFlag; + } + + private static long get64MostSignificantBitsForVersion1() { + LocalDateTime start = LocalDateTime.of(1582, 10, 15, 0, 0, 0); + Duration duration = Duration.between(start, LocalDateTime.now()); + long seconds = duration.getSeconds(); + long nanos = duration.getNano(); + long timeForUuidIn100Nanos = seconds * 10000000 + nanos * 100; + long least12SignificatBitOfTime = (timeForUuidIn100Nanos & 0x000000000000FFFFL) >> 4; + long version = 1 << 12; + return (timeForUuidIn100Nanos & 0xFFFFFFFFFFFF0000L) + version + least12SignificatBitOfTime; + } + + /** + * Type 3 UUID Generation + * + * @throws UnsupportedEncodingException + */ + public static UUID generateType3UUID(String namespace, String name) throws UnsupportedEncodingException { + + byte[] nameSpaceBytes = bytesFromUUID(namespace); + byte[] nameBytes = name.getBytes("UTF-8"); + byte[] result = joinBytes(nameSpaceBytes, nameBytes); + + return UUID.nameUUIDFromBytes(result); } /** @@ -37,28 +64,18 @@ public class UUIDGenerator { return uuid; } - /** - * Type 3 UUID Generation - * - * @throws UnsupportedEncodingException - */ - public static UUID generateType3UUID(String namespace, String name) throws UnsupportedEncodingException { - String source = namespace + name; - byte[] bytes = source.getBytes("UTF-8"); - UUID uuid = UUID.nameUUIDFromBytes(bytes); - return uuid; - } - /** * Type 5 UUID Generation - * - * @throws UnsupportedEncodingException + * + * @throws UnsupportedEncodingException */ public static UUID generateType5UUID(String namespace, String name) throws UnsupportedEncodingException { - String source = namespace + name; - byte[] bytes = source.getBytes("UTF-8"); - UUID uuid = type5UUIDFromBytes(bytes); - return uuid; + + byte[] nameSpaceBytes = bytesFromUUID(namespace); + byte[] nameBytes = name.getBytes("UTF-8"); + byte[] result = joinBytes(nameSpaceBytes, nameBytes); + + return type5UUIDFromBytes(result); } public static UUID type5UUIDFromBytes(byte[] name) { @@ -91,20 +108,20 @@ public class UUIDGenerator { /** * Unique Keys Generation Using Message Digest and Type 4 UUID - * - * @throws NoSuchAlgorithmException - * @throws UnsupportedEncodingException + * + * @throws NoSuchAlgorithmException + * @throws UnsupportedEncodingException */ public static String generateUniqueKeysWithUUIDAndMessageDigest() throws NoSuchAlgorithmException, UnsupportedEncodingException { MessageDigest salt = MessageDigest.getInstance("SHA-256"); salt.update(UUID.randomUUID() - .toString() - .getBytes("UTF-8")); + .toString() + .getBytes("UTF-8")); String digest = bytesToHex(salt.digest()); return digest; } - public static String bytesToHex(byte[] bytes) { + private static String bytesToHex(byte[] bytes) { char[] hexChars = new char[bytes.length * 2]; for (int j = 0; j < bytes.length; j++) { int v = bytes[j] & 0xFF; @@ -114,4 +131,37 @@ public class UUIDGenerator { return new String(hexChars); } -} + private static byte[] bytesFromUUID(String uuidHexString) { + String normalizedUUIDHexString = uuidHexString.replace("-",""); + + assert normalizedUUIDHexString.length() == 32; + + byte[] bytes = new byte[16]; + for (int i = 0; i < 16; i++) { + byte b = hexToByte(normalizedUUIDHexString.substring(i*2, i*2+2)); + bytes[i] = b; + } + return bytes; + } + + public static byte hexToByte(String hexString) { + int firstDigit = Character.digit(hexString.charAt(0),16); + int secondDigit = Character.digit(hexString.charAt(1),16); + return (byte) ((firstDigit << 4) + secondDigit); + } + + public static byte[] joinBytes(byte[] byteArray1, byte[] byteArray2) { + int finalLength = byteArray1.length + byteArray2.length; + byte[] result = new byte[finalLength]; + + for(int i = 0; i < byteArray1.length; i++) { + result[i] = byteArray1[i]; + } + + for(int i = 0; i < byteArray2.length; i++) { + result[byteArray1.length+i] = byteArray2[i]; + } + + return result; + } +} \ No newline at end of file diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java new file mode 100644 index 0000000000..9e08363a63 --- /dev/null +++ b/core-java-modules/core-java/src/test/java/com/baeldung/uuid/UUIDGeneratorUnitTest.java @@ -0,0 +1,64 @@ +package com.baeldung.uuid; + +import org.junit.jupiter.api.Test; + +import java.io.UnsupportedEncodingException; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class UUIDGeneratorUnitTest { + + private static final String NAMESPACE_URL = "6ba7b811-9dad-11d1-80b4-00c04fd430c8"; + private static final String NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8"; + + @Test + public void version_1_UUID_is_generated_with_correct_length_version_and_variant() { + + UUID uuid = UUIDGenerator.generateType1UUID(); + + assertEquals(36, uuid.toString().length()); + assertEquals(1, uuid.version()); + assertEquals(2, uuid.variant()); + } + + @Test + public void version_3_UUID_is_correctly_generated_for_domain_baeldung_com() throws UnsupportedEncodingException { + + UUID uuid = UUIDGenerator.generateType3UUID(NAMESPACE_DNS, "baeldung.com"); + + assertEquals("23785b78-0132-3ac6-aff6-cfd5be162139", uuid.toString()); + assertEquals(3, uuid.version()); + assertEquals(2, uuid.variant()); + } + + @Test + public void version_3_UUID_is_correctly_generated_for_domain_d() throws UnsupportedEncodingException { + + UUID uuid = UUIDGenerator.generateType3UUID(NAMESPACE_DNS, "d"); + + assertEquals("dbd41ecb-f466-33de-b309-1468addfc63b", uuid.toString()); + assertEquals(3, uuid.version()); + assertEquals(2, uuid.variant()); + } + + @Test + public void version_4_UUID_is_generated_with_correct_length_version_and_variant() { + + UUID uuid = UUIDGenerator.generateType4UUID(); + + assertEquals(36, uuid.toString().length()); + assertEquals(4, uuid.version()); + assertEquals(2, uuid.variant()); + } + + @Test + public void version_5_UUID_is_correctly_generated_for_domain_baeldung_com() throws UnsupportedEncodingException { + + UUID uuid = UUIDGenerator.generateType5UUID(NAMESPACE_URL, "baeldung.com"); + + assertEquals("aeff44a5-8a61-52b6-bcbe-c8e5bd7d0300", uuid.toString()); + assertEquals(5, uuid.version()); + assertEquals(2, uuid.variant()); + } +} \ No newline at end of file From 46ebcba3a04c72b526fabdf90801319c87c9016c Mon Sep 17 00:00:00 2001 From: mikr Date: Sun, 7 Jun 2020 13:22:16 +0200 Subject: [PATCH 30/46] JAVA-1749 Move modules language interop and console --- core-java-modules/core-java-console/README.md | 5 + core-java-modules/core-java-console/pom.xml | 142 ++++++++++++++++++ .../java/com/baeldung/asciiart/AsciiArt.java | 0 .../baeldung/console/ConsoleConsoleClass.java | 0 .../baeldung/console/ConsoleScannerClass.java | 0 .../com/baeldung/printf/PrintfExamples.java | 0 .../asciiart/AsciiArtIntegrationTest.java | 7 +- core-java-modules/core-java/README.md | 60 ++++++++ language-interop/README.md | 1 + .../src/main/resources/js/bind.js | 0 .../src/main/resources/js/locations.js | 0 .../src/main/resources/js/math_module.js | 0 .../src/main/resources/js/no_such.js | 0 .../src/main/resources/js/script.js | 0 .../src/main/resources/js/trim.js | 0 .../src/main/resources/js/typed_arrays.js | 0 .../interop/javascript}/NashornUnitTest.java | 8 +- 17 files changed, 214 insertions(+), 9 deletions(-) create mode 100644 core-java-modules/core-java-console/README.md create mode 100644 core-java-modules/core-java-console/pom.xml rename core-java-modules/{core-java => core-java-console}/src/main/java/com/baeldung/asciiart/AsciiArt.java (100%) rename core-java-modules/{core-java => core-java-console}/src/main/java/com/baeldung/console/ConsoleConsoleClass.java (100%) rename core-java-modules/{core-java => core-java-console}/src/main/java/com/baeldung/console/ConsoleScannerClass.java (100%) rename core-java-modules/{core-java => core-java-console}/src/main/java/com/baeldung/printf/PrintfExamples.java (100%) rename core-java-modules/{core-java => core-java-console}/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java (89%) rename {core-java-modules/core-java => language-interop}/src/main/resources/js/bind.js (100%) rename {core-java-modules/core-java => language-interop}/src/main/resources/js/locations.js (100%) rename {core-java-modules/core-java => language-interop}/src/main/resources/js/math_module.js (100%) rename {core-java-modules/core-java => language-interop}/src/main/resources/js/no_such.js (100%) rename {core-java-modules/core-java => language-interop}/src/main/resources/js/script.js (100%) rename {core-java-modules/core-java => language-interop}/src/main/resources/js/trim.js (100%) rename {core-java-modules/core-java => language-interop}/src/main/resources/js/typed_arrays.js (100%) rename {core-java-modules/core-java/src/test/java/com/baeldung/scripting => language-interop/src/test/java/com/baeldung/language/interop/javascript}/NashornUnitTest.java (94%) diff --git a/core-java-modules/core-java-console/README.md b/core-java-modules/core-java-console/README.md new file mode 100644 index 0000000000..725e2482bb --- /dev/null +++ b/core-java-modules/core-java-console/README.md @@ -0,0 +1,5 @@ +#Core Java Console + +[Read and Write User Input in Java](http://www.baeldung.com/java-console-input-output) +[Formatting with printf() in Java](https://www.baeldung.com/java-printstream-printf) +[ASCII Art in Java](http://www.baeldung.com/ascii-art-in-java) \ No newline at end of file diff --git a/core-java-modules/core-java-console/pom.xml b/core-java-modules/core-java-console/pom.xml new file mode 100644 index 0000000000..1d58d8c253 --- /dev/null +++ b/core-java-modules/core-java-console/pom.xml @@ -0,0 +1,142 @@ + + + 4.0.0 + core-java-console + 0.1.0-SNAPSHOT + core-java-console + jar + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + ../ + + + + core-java-console + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/libs + + + + + + + org.codehaus.mojo + exec-maven-plugin + ${exec-maven-plugin.version} + + java + com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed + + -Xmx300m + -XX:+UseParallelGC + -classpath + + com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven-javadoc-plugin.version} + + ${source.version} + ${target.version} + + + + + + + + integration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*ManualTest.java + + + **/*IntegrationTest.java + **/*IntTest.java + + + + + + + json + + + + + org.codehaus.mojo + exec-maven-plugin + ${exec-maven-plugin.version} + + + run-benchmarks + + none + + exec + + + test + java + + -classpath + + org.openjdk.jmh.Main + .* + + + + + + + + + + + + 3.0.0-M1 + 1.6.0 + 1.8 + 1.8 + + + diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/asciiart/AsciiArt.java b/core-java-modules/core-java-console/src/main/java/com/baeldung/asciiart/AsciiArt.java similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/asciiart/AsciiArt.java rename to core-java-modules/core-java-console/src/main/java/com/baeldung/asciiart/AsciiArt.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/console/ConsoleConsoleClass.java b/core-java-modules/core-java-console/src/main/java/com/baeldung/console/ConsoleConsoleClass.java similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/console/ConsoleConsoleClass.java rename to core-java-modules/core-java-console/src/main/java/com/baeldung/console/ConsoleConsoleClass.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/console/ConsoleScannerClass.java b/core-java-modules/core-java-console/src/main/java/com/baeldung/console/ConsoleScannerClass.java similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/console/ConsoleScannerClass.java rename to core-java-modules/core-java-console/src/main/java/com/baeldung/console/ConsoleScannerClass.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/printf/PrintfExamples.java b/core-java-modules/core-java-console/src/main/java/com/baeldung/printf/PrintfExamples.java similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/printf/PrintfExamples.java rename to core-java-modules/core-java-console/src/main/java/com/baeldung/printf/PrintfExamples.java diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java b/core-java-modules/core-java-console/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java similarity index 89% rename from core-java-modules/core-java/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java rename to core-java-modules/core-java-console/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java index 8ab1695395..4bfcbe5a36 100644 --- a/core-java-modules/core-java/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java +++ b/core-java-modules/core-java-console/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java @@ -1,10 +1,9 @@ package com.baeldung.asciiart; -import java.awt.Font; - +import com.baeldung.asciiart.AsciiArt.Settings; import org.junit.Test; -import com.baeldung.asciiart.AsciiArt.Settings; +import java.awt.*; public class AsciiArtIntegrationTest { @@ -15,6 +14,8 @@ public class AsciiArtIntegrationTest { Settings settings = asciiArt.new Settings(new Font("SansSerif", Font.BOLD, 24), text.length() * 30, 30); // 30 pixel width per character asciiArt.drawString(text, "*", settings); + + throw new NullPointerException(); } } diff --git a/core-java-modules/core-java/README.md b/core-java-modules/core-java/README.md index bffb88cafb..2123a61499 100644 --- a/core-java-modules/core-java/README.md +++ b/core-java-modules/core-java/README.md @@ -33,3 +33,63 @@ - [Making a JSON POST Request With HttpURLConnection](https://www.baeldung.com/httpurlconnection-post) - [How to Find an Exception’s Root Cause in Java](https://www.baeldung.com/java-exception-root-cause) - [Convert Hex to ASCII in Java](https://www.baeldung.com/java-convert-hex-to-ascii) + + +#New module structure +########################### + +#Leave in core-java: +[Getting Started with Java Properties](http://www.baeldung.com/java-properties) +[Java Money and the Currency API](http://www.baeldung.com/java-money-and-currency) +[Introduction to Java Serialization](http://www.baeldung.com/java-serialization) +[Guide to UUID in Java](http://www.baeldung.com/java-uuid) +[Compiling Java *.class Files with javac](http://www.baeldung.com/javac) +[Introduction to Javadoc](http://www.baeldung.com/javadoc) +[Guide to the Externalizable Interface in Java](http://www.baeldung.com/java-externalizable) +[What is the serialVersionUID?](http://www.baeldung.com/java-serial-version-uid) +[A Guide to the ResourceBundle](http://www.baeldung.com/java-resourcebundle) +[Merging java.util.Properties Objects](https://www.baeldung.com/java-merging-properties) + +#Move to language interop (Done) +[Introduction to Nashorn](http://www.baeldung.com/java-nashorn) + +#Move to new new package: core-java-console (Done) +[Read and Write User Input in Java](http://www.baeldung.com/java-console-input-output) +[Formatting with printf() in Java](https://www.baeldung.com/java-printstream-printf) +[ASCII Art in Java](http://www.baeldung.com/ascii-art-in-java) + +#Move to core-java-string-operations-2 +[Guide to Character Encoding](https://www.baeldung.com/java-char-encoding) +[Convert Hex to ASCII in Java](https://www.baeldung.com/java-convert-hex-to-ascii) #remove additional readme file + +#Move to core-javadatetime-operations-2 +[Finding Leap Years in Java](https://www.baeldung.com/java-leap-year) + +#Move to core-java-time-measurements +[Java Timer](http://www.baeldung.com/java-timer-and-timertask) + +#Move to core-java-reflection +[How to Get a Name of a Method Being Executed?](http://www.baeldung.com/java-name-of-executing-method) + +#Move to core-java-streams +[How to Find all Getters Returning Null](http://www.baeldung.com/java-getters-returning-null) + +#Move to core-java-jvm +[How to Get the Size of an Object in Java](http://www.baeldung.com/java-size-of-object) + +#Move to data-structures module +[Graphs in Java](https://www.baeldung.com/java-graphs) + +#Move to core-java-collections-3 +[Quick Guide to the Java Stack](https://www.baeldung.com/java-stack) + +#These are already in another module +[Using Curl in Java](https://www.baeldung.com/java-curl) #Core Java Networking (Part 2) +[Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin) # Core Java Sun +[Java Global Exception Handler](http://www.baeldung.com/java-global-exception-handler) #Core Java Exceptions +[Java – Try with Resources](https://www.baeldung.com/java-try-with-resources) #Core Java Exceptions +[How to Find an Exception’s Root Cause in Java](https://www.baeldung.com/java-exception-root-cause) #Core Java Exceptions +[JVM Log Forging](http://www.baeldung.com/jvm-log-forging) #Core Java JVM +[Making a JSON POST Request With HttpURLConnection](https://www.baeldung.com/httpurlconnection-post) #Core Java Networking (Part 2) +[Common Java Exceptions](http://www.baeldung.com/java-common-exceptions) #Core Java Exceptions +[Retrieve Fields from a Java Class Using Reflection](https://www.baeldung.com/java-reflection-class-fields) #Core Java Reflection \ No newline at end of file diff --git a/language-interop/README.md b/language-interop/README.md index 458f34a119..f4f2fc0816 100644 --- a/language-interop/README.md +++ b/language-interop/README.md @@ -5,3 +5,4 @@ This module contains articles about Java interop with other language integration ### Relevant Articles: - [How to Call Python From Java](https://www.baeldung.com/java-working-with-python) +- [Introduction to Nashorn](http://www.baeldung.com/java-nashorn) diff --git a/core-java-modules/core-java/src/main/resources/js/bind.js b/language-interop/src/main/resources/js/bind.js similarity index 100% rename from core-java-modules/core-java/src/main/resources/js/bind.js rename to language-interop/src/main/resources/js/bind.js diff --git a/core-java-modules/core-java/src/main/resources/js/locations.js b/language-interop/src/main/resources/js/locations.js similarity index 100% rename from core-java-modules/core-java/src/main/resources/js/locations.js rename to language-interop/src/main/resources/js/locations.js diff --git a/core-java-modules/core-java/src/main/resources/js/math_module.js b/language-interop/src/main/resources/js/math_module.js similarity index 100% rename from core-java-modules/core-java/src/main/resources/js/math_module.js rename to language-interop/src/main/resources/js/math_module.js diff --git a/core-java-modules/core-java/src/main/resources/js/no_such.js b/language-interop/src/main/resources/js/no_such.js similarity index 100% rename from core-java-modules/core-java/src/main/resources/js/no_such.js rename to language-interop/src/main/resources/js/no_such.js diff --git a/core-java-modules/core-java/src/main/resources/js/script.js b/language-interop/src/main/resources/js/script.js similarity index 100% rename from core-java-modules/core-java/src/main/resources/js/script.js rename to language-interop/src/main/resources/js/script.js diff --git a/core-java-modules/core-java/src/main/resources/js/trim.js b/language-interop/src/main/resources/js/trim.js similarity index 100% rename from core-java-modules/core-java/src/main/resources/js/trim.js rename to language-interop/src/main/resources/js/trim.js diff --git a/core-java-modules/core-java/src/main/resources/js/typed_arrays.js b/language-interop/src/main/resources/js/typed_arrays.js similarity index 100% rename from core-java-modules/core-java/src/main/resources/js/typed_arrays.js rename to language-interop/src/main/resources/js/typed_arrays.js diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/scripting/NashornUnitTest.java b/language-interop/src/test/java/com/baeldung/language/interop/javascript/NashornUnitTest.java similarity index 94% rename from core-java-modules/core-java/src/test/java/com/baeldung/scripting/NashornUnitTest.java rename to language-interop/src/test/java/com/baeldung/language/interop/javascript/NashornUnitTest.java index 9abe8a927c..a9e4243f9d 100644 --- a/core-java-modules/core-java/src/test/java/com/baeldung/scripting/NashornUnitTest.java +++ b/language-interop/src/test/java/com/baeldung/language/interop/javascript/NashornUnitTest.java @@ -1,14 +1,10 @@ -package com.baeldung.scripting; +package com.baeldung.language.interop.javascript; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import javax.script.Bindings; -import javax.script.Invocable; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; +import javax.script.*; import java.io.InputStreamReader; import java.util.List; import java.util.Map; From 5a753ba3842c44462d49ec546979ad57bf8f16c0 Mon Sep 17 00:00:00 2001 From: mikr Date: Sun, 7 Jun 2020 16:52:25 +0200 Subject: [PATCH 31/46] JAVA-1522 Split core-java-modules/core-java module --- .../core-java-collections-3/README.md | 1 + .../collections}/stack/StackUnitTest.java | 0 .../asciiart/AsciiArtIntegrationTest.java | 3 - .../core-java-date-operations-2/README.md | 1 + .../baeldung/leapyear/LeapYearUnitTest.java | 0 core-java-modules/core-java-jvm/README.md | 1 + .../objectsize/InstrumentationAgent.java | 0 .../objectsize/InstrumentationExample.java | 0 .../java/com/baeldung/objectsize/MANIFEST.MF | 0 .../core-java-reflection/README.MD | 2 + ...CurrentlyExecutedMethodFinderUnitTest.java | 0 .../core-java-string-operations-2/README.md | 2 + .../encoding/CharacterEncodingExamples.java | 0 .../hexToAscii/HexToAsciiUnitTest.java | 0 .../java/com/baeldung/hexToAscii/README.md | 0 .../src/test/resources/output.pdf | Bin 0 -> 142786 bytes .../core-java-time-measurements/README.md | 1 + .../baeldung/timer/DatabaseMigrationTask.java | 0 .../com/baeldung/timer/NewsletterTask.java | 0 .../{java => }/clock/ClockUnitTest.java | 2 +- .../timer/DatabaseMigrationTaskUnitTest.java | 0 .../timer/JavaTimerLongRunningUnitTest.java | 0 .../timer/NewsletterTaskUnitTest.java | 0 core-java-modules/core-java/README.md | 82 ------------------ data-structures/README.md | 1 + .../main/java/com/baeldung/graph/Graph.java | 0 .../com/baeldung/graph/GraphTraversal.java | 0 .../com/baeldung/graph/GraphUnitTest.java | 0 28 files changed, 10 insertions(+), 86 deletions(-) rename core-java-modules/{core-java/src/test/java/com/baeldung => core-java-collections-3/src/test/java/com/baeldung/collections}/stack/StackUnitTest.java (100%) rename core-java-modules/{core-java => core-java-date-operations-2}/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java (100%) rename core-java-modules/{core-java => core-java-jvm}/src/main/java/com/baeldung/objectsize/InstrumentationAgent.java (100%) rename core-java-modules/{core-java => core-java-jvm}/src/main/java/com/baeldung/objectsize/InstrumentationExample.java (100%) rename core-java-modules/{core-java => core-java-jvm}/src/main/java/com/baeldung/objectsize/MANIFEST.MF (100%) rename core-java-modules/{core-java/src/test/java/com/baeldung/java => core-java-reflection/src/test/java/com/baeldung}/currentmethod/CurrentlyExecutedMethodFinderUnitTest.java (100%) rename core-java-modules/{core-java => core-java-string-operations-2}/src/main/java/com/baeldung/encoding/CharacterEncodingExamples.java (100%) rename core-java-modules/{core-java => core-java-string-operations-2}/src/test/java/com/baeldung/hexToAscii/HexToAsciiUnitTest.java (100%) rename core-java-modules/{core-java => core-java-string-operations-2}/src/test/java/com/baeldung/hexToAscii/README.md (100%) create mode 100644 core-java-modules/core-java-string-operations-2/src/test/resources/output.pdf rename core-java-modules/{core-java => core-java-time-measurements}/src/main/java/com/baeldung/timer/DatabaseMigrationTask.java (100%) rename core-java-modules/{core-java => core-java-time-measurements}/src/main/java/com/baeldung/timer/NewsletterTask.java (100%) rename core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/{java => }/clock/ClockUnitTest.java (99%) rename core-java-modules/{core-java => core-java-time-measurements}/src/test/java/com/baeldung/timer/DatabaseMigrationTaskUnitTest.java (100%) rename core-java-modules/{core-java => core-java-time-measurements}/src/test/java/com/baeldung/timer/JavaTimerLongRunningUnitTest.java (100%) rename core-java-modules/{core-java => core-java-time-measurements}/src/test/java/com/baeldung/timer/NewsletterTaskUnitTest.java (100%) rename {core-java-modules/core-java => data-structures}/src/main/java/com/baeldung/graph/Graph.java (100%) rename {core-java-modules/core-java => data-structures}/src/main/java/com/baeldung/graph/GraphTraversal.java (100%) rename {core-java-modules/core-java => data-structures}/src/test/java/com/baeldung/graph/GraphUnitTest.java (100%) diff --git a/core-java-modules/core-java-collections-3/README.md b/core-java-modules/core-java-collections-3/README.md index 9218384640..fb983d9abc 100644 --- a/core-java-modules/core-java-collections-3/README.md +++ b/core-java-modules/core-java-collections-3/README.md @@ -9,3 +9,4 @@ - [Differences Between Collection.clear() and Collection.removeAll()](https://www.baeldung.com/java-collection-clear-vs-removeall) - [Performance of contains() in a HashSet vs ArrayList](https://www.baeldung.com/java-hashset-arraylist-contains-performance) - [Fail-Safe Iterator vs Fail-Fast Iterator](https://www.baeldung.com/java-fail-safe-vs-fail-fast-iterator) +- [Quick Guide to the Java Stack](https://www.baeldung.com/java-stack) diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/stack/StackUnitTest.java b/core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/stack/StackUnitTest.java similarity index 100% rename from core-java-modules/core-java/src/test/java/com/baeldung/stack/StackUnitTest.java rename to core-java-modules/core-java-collections-3/src/test/java/com/baeldung/collections/stack/StackUnitTest.java diff --git a/core-java-modules/core-java-console/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java b/core-java-modules/core-java-console/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java index 4bfcbe5a36..a8c42fbeb1 100644 --- a/core-java-modules/core-java-console/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java +++ b/core-java-modules/core-java-console/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java @@ -14,8 +14,5 @@ public class AsciiArtIntegrationTest { Settings settings = asciiArt.new Settings(new Font("SansSerif", Font.BOLD, 24), text.length() * 30, 30); // 30 pixel width per character asciiArt.drawString(text, "*", settings); - - throw new NullPointerException(); } - } diff --git a/core-java-modules/core-java-date-operations-2/README.md b/core-java-modules/core-java-date-operations-2/README.md index 19c7b98d30..6dc1302d99 100644 --- a/core-java-modules/core-java-date-operations-2/README.md +++ b/core-java-modules/core-java-date-operations-2/README.md @@ -8,4 +8,5 @@ This module contains articles about date operations in Java. - [Converting Java Date to OffsetDateTime](https://www.baeldung.com/java-convert-date-to-offsetdatetime) - [How to Set the JVM Time Zone](https://www.baeldung.com/java-jvm-time-zone) - [How to determine day of week by passing specific date in Java?](https://www.baeldung.com/java-get-day-of-week) +- [Finding Leap Years in Java](https://www.baeldung.com/java-leap-year) - [[<-- Prev]](/core-java-modules/core-java-date-operations-1) diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java b/core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java similarity index 100% rename from core-java-modules/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java rename to core-java-modules/core-java-date-operations-2/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java diff --git a/core-java-modules/core-java-jvm/README.md b/core-java-modules/core-java-jvm/README.md index 2f80ea7372..0dae790ec0 100644 --- a/core-java-modules/core-java-jvm/README.md +++ b/core-java-modules/core-java-jvm/README.md @@ -12,3 +12,4 @@ This module contains articles about working with the Java Virtual Machine (JVM). - [Guide to System.gc()](https://www.baeldung.com/java-system-gc) - [Runtime.getRuntime().halt() vs System.exit() in Java](https://www.baeldung.com/java-runtime-halt-vs-system-exit) - [Adding Shutdown Hooks for JVM Applications](https://www.baeldung.com/jvm-shutdown-hooks) +- [How to Get the Size of an Object in Java](http://www.baeldung.com/java-size-of-object) diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/objectsize/InstrumentationAgent.java b/core-java-modules/core-java-jvm/src/main/java/com/baeldung/objectsize/InstrumentationAgent.java similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/objectsize/InstrumentationAgent.java rename to core-java-modules/core-java-jvm/src/main/java/com/baeldung/objectsize/InstrumentationAgent.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/objectsize/InstrumentationExample.java b/core-java-modules/core-java-jvm/src/main/java/com/baeldung/objectsize/InstrumentationExample.java similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/objectsize/InstrumentationExample.java rename to core-java-modules/core-java-jvm/src/main/java/com/baeldung/objectsize/InstrumentationExample.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/objectsize/MANIFEST.MF b/core-java-modules/core-java-jvm/src/main/java/com/baeldung/objectsize/MANIFEST.MF similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/objectsize/MANIFEST.MF rename to core-java-modules/core-java-jvm/src/main/java/com/baeldung/objectsize/MANIFEST.MF diff --git a/core-java-modules/core-java-reflection/README.MD b/core-java-modules/core-java-reflection/README.MD index 5aed62b378..d6b3a02e6a 100644 --- a/core-java-modules/core-java-reflection/README.MD +++ b/core-java-modules/core-java-reflection/README.MD @@ -8,3 +8,5 @@ - [Changing Annotation Parameters At Runtime](http://www.baeldung.com/java-reflection-change-annotation-params) - [Dynamic Proxies in Java](http://www.baeldung.com/java-dynamic-proxies) - [What Causes java.lang.reflect.InvocationTargetException?](https://www.baeldung.com/java-lang-reflect-invocationtargetexception) +- [How to Find all Getters Returning Null](http://www.baeldung.com/java-getters-returning-null) +- [How to Get a Name of a Method Being Executed?](http://www.baeldung.com/java-name-of-executing-method) diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/java/currentmethod/CurrentlyExecutedMethodFinderUnitTest.java b/core-java-modules/core-java-reflection/src/test/java/com/baeldung/currentmethod/CurrentlyExecutedMethodFinderUnitTest.java similarity index 100% rename from core-java-modules/core-java/src/test/java/com/baeldung/java/currentmethod/CurrentlyExecutedMethodFinderUnitTest.java rename to core-java-modules/core-java-reflection/src/test/java/com/baeldung/currentmethod/CurrentlyExecutedMethodFinderUnitTest.java diff --git a/core-java-modules/core-java-string-operations-2/README.md b/core-java-modules/core-java-string-operations-2/README.md index 2f54aa9467..cafb3b9017 100644 --- a/core-java-modules/core-java-string-operations-2/README.md +++ b/core-java-modules/core-java-string-operations-2/README.md @@ -12,4 +12,6 @@ This module contains articles about string operations. - [L-Trim and R-Trim Alternatives in Java](https://www.baeldung.com/java-trim-alternatives) - [Java Convert PDF to Base64](https://www.baeldung.com/java-convert-pdf-to-base64) - [Encode a String to UTF-8 in Java](https://www.baeldung.com/java-string-encode-utf-8) +- [Guide to Character Encoding](https://www.baeldung.com/java-char-encoding) +- [Convert Hex to ASCII in Java](https://www.baeldung.com/java-convert-hex-to-ascii) #remove additional readme file - More articles: [[<-- prev]](../core-java-string-operations) diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/encoding/CharacterEncodingExamples.java b/core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/encoding/CharacterEncodingExamples.java similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/encoding/CharacterEncodingExamples.java rename to core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/encoding/CharacterEncodingExamples.java diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/hexToAscii/HexToAsciiUnitTest.java b/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/hexToAscii/HexToAsciiUnitTest.java similarity index 100% rename from core-java-modules/core-java/src/test/java/com/baeldung/hexToAscii/HexToAsciiUnitTest.java rename to core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/hexToAscii/HexToAsciiUnitTest.java diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/hexToAscii/README.md b/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/hexToAscii/README.md similarity index 100% rename from core-java-modules/core-java/src/test/java/com/baeldung/hexToAscii/README.md rename to core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/hexToAscii/README.md diff --git a/core-java-modules/core-java-string-operations-2/src/test/resources/output.pdf b/core-java-modules/core-java-string-operations-2/src/test/resources/output.pdf new file mode 100644 index 0000000000000000000000000000000000000000..94d947797464aa493ba9634f4e5f38ad2ca4717a GIT binary patch literal 142786 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 literal 0 HcmV?d00001 diff --git a/core-java-modules/core-java-time-measurements/README.md b/core-java-modules/core-java-time-measurements/README.md index 1bd277b6b1..a3e8b71ae8 100644 --- a/core-java-modules/core-java-time-measurements/README.md +++ b/core-java-modules/core-java-time-measurements/README.md @@ -6,3 +6,4 @@ This module contains articles about the measurement of time in Java. - [Guide to the Java Clock Class](http://www.baeldung.com/java-clock) - [Measure Elapsed Time in Java](http://www.baeldung.com/java-measure-elapsed-time) - [Overriding System Time for Testing in Java](https://www.baeldung.com/java-override-system-time) +- [Java Timer](http://www.baeldung.com/java-timer-and-timertask) diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/timer/DatabaseMigrationTask.java b/core-java-modules/core-java-time-measurements/src/main/java/com/baeldung/timer/DatabaseMigrationTask.java similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/timer/DatabaseMigrationTask.java rename to core-java-modules/core-java-time-measurements/src/main/java/com/baeldung/timer/DatabaseMigrationTask.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/timer/NewsletterTask.java b/core-java-modules/core-java-time-measurements/src/main/java/com/baeldung/timer/NewsletterTask.java similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/timer/NewsletterTask.java rename to core-java-modules/core-java-time-measurements/src/main/java/com/baeldung/timer/NewsletterTask.java diff --git a/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/java/clock/ClockUnitTest.java b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/clock/ClockUnitTest.java similarity index 99% rename from core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/java/clock/ClockUnitTest.java rename to core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/clock/ClockUnitTest.java index e83ba7afc8..4e34271214 100644 --- a/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/java/clock/ClockUnitTest.java +++ b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/clock/ClockUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.java.clock; +package com.baeldung.clock; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/timer/DatabaseMigrationTaskUnitTest.java b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/timer/DatabaseMigrationTaskUnitTest.java similarity index 100% rename from core-java-modules/core-java/src/test/java/com/baeldung/timer/DatabaseMigrationTaskUnitTest.java rename to core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/timer/DatabaseMigrationTaskUnitTest.java diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/timer/JavaTimerLongRunningUnitTest.java b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/timer/JavaTimerLongRunningUnitTest.java similarity index 100% rename from core-java-modules/core-java/src/test/java/com/baeldung/timer/JavaTimerLongRunningUnitTest.java rename to core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/timer/JavaTimerLongRunningUnitTest.java diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/timer/NewsletterTaskUnitTest.java b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/timer/NewsletterTaskUnitTest.java similarity index 100% rename from core-java-modules/core-java/src/test/java/com/baeldung/timer/NewsletterTaskUnitTest.java rename to core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/timer/NewsletterTaskUnitTest.java diff --git a/core-java-modules/core-java/README.md b/core-java-modules/core-java/README.md index 2123a61499..7781382ae5 100644 --- a/core-java-modules/core-java/README.md +++ b/core-java-modules/core-java/README.md @@ -1,44 +1,6 @@ ## Core Java Cookbooks and Examples ### Relevant Articles: -- [Java Timer](http://www.baeldung.com/java-timer-and-timertask) -- [Getting Started with Java Properties](http://www.baeldung.com/java-properties) -- [Introduction to Nashorn](http://www.baeldung.com/java-nashorn) -- [Java Money and the Currency API](http://www.baeldung.com/java-money-and-currency) -- [JVM Log Forging](http://www.baeldung.com/jvm-log-forging) -- [How to Find all Getters Returning Null](http://www.baeldung.com/java-getters-returning-null) -- [How to Get a Name of a Method Being Executed?](http://www.baeldung.com/java-name-of-executing-method) -- [Introduction to Java Serialization](http://www.baeldung.com/java-serialization) -- [Guide to UUID in Java](http://www.baeldung.com/java-uuid) -- [Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin) -- [Quick Guide to the Java Stack](https://www.baeldung.com/java-stack) -- [Compiling Java *.class Files with javac](http://www.baeldung.com/javac) -- [Introduction to Javadoc](http://www.baeldung.com/javadoc) -- [Guide to the Externalizable Interface in Java](http://www.baeldung.com/java-externalizable) -- [ASCII Art in Java](http://www.baeldung.com/ascii-art-in-java) -- [What is the serialVersionUID?](http://www.baeldung.com/java-serial-version-uid) -- [A Guide to the ResourceBundle](http://www.baeldung.com/java-resourcebundle) -- [Java Global Exception Handler](http://www.baeldung.com/java-global-exception-handler) -- [How to Get the Size of an Object in Java](http://www.baeldung.com/java-size-of-object) -- [Common Java Exceptions](http://www.baeldung.com/java-common-exceptions) -- [Merging java.util.Properties Objects](https://www.baeldung.com/java-merging-properties) -- [Java – Try with Resources](https://www.baeldung.com/java-try-with-resources) -- [Guide to Character Encoding](https://www.baeldung.com/java-char-encoding) -- [Graphs in Java](https://www.baeldung.com/java-graphs) -- [Read and Write User Input in Java](http://www.baeldung.com/java-console-input-output) -- [Formatting with printf() in Java](https://www.baeldung.com/java-printstream-printf) -- [Retrieve Fields from a Java Class Using Reflection](https://www.baeldung.com/java-reflection-class-fields) -- [Using Curl in Java](https://www.baeldung.com/java-curl) -- [Finding Leap Years in Java](https://www.baeldung.com/java-leap-year) -- [Making a JSON POST Request With HttpURLConnection](https://www.baeldung.com/httpurlconnection-post) -- [How to Find an Exception’s Root Cause in Java](https://www.baeldung.com/java-exception-root-cause) -- [Convert Hex to ASCII in Java](https://www.baeldung.com/java-convert-hex-to-ascii) - - -#New module structure -########################### - -#Leave in core-java: [Getting Started with Java Properties](http://www.baeldung.com/java-properties) [Java Money and the Currency API](http://www.baeldung.com/java-money-and-currency) [Introduction to Java Serialization](http://www.baeldung.com/java-serialization) @@ -49,47 +11,3 @@ [What is the serialVersionUID?](http://www.baeldung.com/java-serial-version-uid) [A Guide to the ResourceBundle](http://www.baeldung.com/java-resourcebundle) [Merging java.util.Properties Objects](https://www.baeldung.com/java-merging-properties) - -#Move to language interop (Done) -[Introduction to Nashorn](http://www.baeldung.com/java-nashorn) - -#Move to new new package: core-java-console (Done) -[Read and Write User Input in Java](http://www.baeldung.com/java-console-input-output) -[Formatting with printf() in Java](https://www.baeldung.com/java-printstream-printf) -[ASCII Art in Java](http://www.baeldung.com/ascii-art-in-java) - -#Move to core-java-string-operations-2 -[Guide to Character Encoding](https://www.baeldung.com/java-char-encoding) -[Convert Hex to ASCII in Java](https://www.baeldung.com/java-convert-hex-to-ascii) #remove additional readme file - -#Move to core-javadatetime-operations-2 -[Finding Leap Years in Java](https://www.baeldung.com/java-leap-year) - -#Move to core-java-time-measurements -[Java Timer](http://www.baeldung.com/java-timer-and-timertask) - -#Move to core-java-reflection -[How to Get a Name of a Method Being Executed?](http://www.baeldung.com/java-name-of-executing-method) - -#Move to core-java-streams -[How to Find all Getters Returning Null](http://www.baeldung.com/java-getters-returning-null) - -#Move to core-java-jvm -[How to Get the Size of an Object in Java](http://www.baeldung.com/java-size-of-object) - -#Move to data-structures module -[Graphs in Java](https://www.baeldung.com/java-graphs) - -#Move to core-java-collections-3 -[Quick Guide to the Java Stack](https://www.baeldung.com/java-stack) - -#These are already in another module -[Using Curl in Java](https://www.baeldung.com/java-curl) #Core Java Networking (Part 2) -[Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin) # Core Java Sun -[Java Global Exception Handler](http://www.baeldung.com/java-global-exception-handler) #Core Java Exceptions -[Java – Try with Resources](https://www.baeldung.com/java-try-with-resources) #Core Java Exceptions -[How to Find an Exception’s Root Cause in Java](https://www.baeldung.com/java-exception-root-cause) #Core Java Exceptions -[JVM Log Forging](http://www.baeldung.com/jvm-log-forging) #Core Java JVM -[Making a JSON POST Request With HttpURLConnection](https://www.baeldung.com/httpurlconnection-post) #Core Java Networking (Part 2) -[Common Java Exceptions](http://www.baeldung.com/java-common-exceptions) #Core Java Exceptions -[Retrieve Fields from a Java Class Using Reflection](https://www.baeldung.com/java-reflection-class-fields) #Core Java Reflection \ No newline at end of file diff --git a/data-structures/README.md b/data-structures/README.md index f9ca78679a..e3436695ce 100644 --- a/data-structures/README.md +++ b/data-structures/README.md @@ -10,3 +10,4 @@ This module contains articles about data structures in Java - [How to Print a Binary Tree Diagram](https://www.baeldung.com/java-print-binary-tree-diagram) - [Introduction to Big Queue](https://www.baeldung.com/java-big-queue) - [Guide to AVL Trees in Java](https://www.baeldung.com/java-avl-trees) +- [Graphs in Java](https://www.baeldung.com/java-graphs) diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/graph/Graph.java b/data-structures/src/main/java/com/baeldung/graph/Graph.java similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/graph/Graph.java rename to data-structures/src/main/java/com/baeldung/graph/Graph.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/graph/GraphTraversal.java b/data-structures/src/main/java/com/baeldung/graph/GraphTraversal.java similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/graph/GraphTraversal.java rename to data-structures/src/main/java/com/baeldung/graph/GraphTraversal.java diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/graph/GraphUnitTest.java b/data-structures/src/test/java/com/baeldung/graph/GraphUnitTest.java similarity index 100% rename from core-java-modules/core-java/src/test/java/com/baeldung/graph/GraphUnitTest.java rename to data-structures/src/test/java/com/baeldung/graph/GraphUnitTest.java From 4fa2ffb229c34b608657121b48eb552c9bfe7fbb Mon Sep 17 00:00:00 2001 From: "amit.pandey" Date: Sun, 7 Jun 2020 20:28:16 +0530 Subject: [PATCH 32/46] pom formatting - make artifact name same as module name --- core-java-modules/core-java-8-datetime-2/pom.xml | 3 +-- maven-all/versions-maven-plugin/original/pom.xml | 2 +- persistence-modules/r2dbc/pom.xml | 2 +- quarkus-extension/quarkus-liquibase/pom.xml | 2 +- twitter4j/pom.xml | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/core-java-modules/core-java-8-datetime-2/pom.xml b/core-java-modules/core-java-8-datetime-2/pom.xml index 629ce5234d..f66a89ca55 100644 --- a/core-java-modules/core-java-8-datetime-2/pom.xml +++ b/core-java-modules/core-java-8-datetime-2/pom.xml @@ -4,7 +4,7 @@ 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 - core-java-8-datetime + core-java-8-datetime-2 ${project.parent.version} core-java-8-datetime jar @@ -41,7 +41,6 @@ - core-java-datetime-java8 src/main/resources diff --git a/maven-all/versions-maven-plugin/original/pom.xml b/maven-all/versions-maven-plugin/original/pom.xml index 54140aec9b..f81596661e 100644 --- a/maven-all/versions-maven-plugin/original/pom.xml +++ b/maven-all/versions-maven-plugin/original/pom.xml @@ -4,7 +4,7 @@ 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 - versions-maven-plugin-example + original 0.0.1-SNAPSHOT diff --git a/persistence-modules/r2dbc/pom.xml b/persistence-modules/r2dbc/pom.xml index 70ff8d6a87..b1de88e9ea 100644 --- a/persistence-modules/r2dbc/pom.xml +++ b/persistence-modules/r2dbc/pom.xml @@ -4,7 +4,7 @@ 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.examples.r2dbc - r2dbc-example + r2dbc 0.0.1-SNAPSHOT r2dbc Sample R2DBC Project diff --git a/quarkus-extension/quarkus-liquibase/pom.xml b/quarkus-extension/quarkus-liquibase/pom.xml index 8ed6555ed7..fdede2000e 100644 --- a/quarkus-extension/quarkus-liquibase/pom.xml +++ b/quarkus-extension/quarkus-liquibase/pom.xml @@ -4,7 +4,7 @@ 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.quarkus.liquibase - quarkus-liquibase-parent + quarkus-liquibase quarkus-liquibase pom diff --git a/twitter4j/pom.xml b/twitter4j/pom.xml index 274b5c75c3..0c36e72892 100644 --- a/twitter4j/pom.xml +++ b/twitter4j/pom.xml @@ -2,7 +2,7 @@ 4.0.0 - twitter4J + twitter4j twitter4J jar From 1a5e943886db4b0234c674605cc09504d0384784 Mon Sep 17 00:00:00 2001 From: "amit.pandey" Date: Sun, 7 Jun 2020 21:28:59 +0530 Subject: [PATCH 33/46] updated the child pom as quarkus-extension/quarkus-liquibase pom artifactId is changed --- quarkus-extension/quarkus-liquibase/deployment/pom.xml | 2 +- quarkus-extension/quarkus-liquibase/runtime/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/quarkus-extension/quarkus-liquibase/deployment/pom.xml b/quarkus-extension/quarkus-liquibase/deployment/pom.xml index 5c6b56e152..d7f1f995ff 100644 --- a/quarkus-extension/quarkus-liquibase/deployment/pom.xml +++ b/quarkus-extension/quarkus-liquibase/deployment/pom.xml @@ -8,7 +8,7 @@ com.baeldung.quarkus.liquibase - quarkus-liquibase-parent + quarkus-liquibase 1.0-SNAPSHOT diff --git a/quarkus-extension/quarkus-liquibase/runtime/pom.xml b/quarkus-extension/quarkus-liquibase/runtime/pom.xml index 760e6ab719..5d3b05ef92 100644 --- a/quarkus-extension/quarkus-liquibase/runtime/pom.xml +++ b/quarkus-extension/quarkus-liquibase/runtime/pom.xml @@ -7,7 +7,7 @@ com.baeldung.quarkus.liquibase - quarkus-liquibase-parent + quarkus-liquibase 1.0-SNAPSHOT From fdcf192cbe13f85507ab18e45f78c8367da5f6f5 Mon Sep 17 00:00:00 2001 From: mikr Date: Sun, 7 Jun 2020 18:17:43 +0200 Subject: [PATCH 34/46] JAVA-1522 Fix integration test for encoding package --- .../com/baeldung/encoding/CharacterEncodingExamplesUnitTest.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core-java-modules/{core-java => core-java-string-operations-2}/src/test/java/com/baeldung/encoding/CharacterEncodingExamplesUnitTest.java (100%) diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/encoding/CharacterEncodingExamplesUnitTest.java b/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/encoding/CharacterEncodingExamplesUnitTest.java similarity index 100% rename from core-java-modules/core-java/src/test/java/com/baeldung/encoding/CharacterEncodingExamplesUnitTest.java rename to core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/encoding/CharacterEncodingExamplesUnitTest.java From 7b8b9390c737a12a5d6e228f0b50f7c37b5fde9d Mon Sep 17 00:00:00 2001 From: mikr Date: Sun, 7 Jun 2020 21:46:55 +0200 Subject: [PATCH 35/46] JAVA-1522 Fix integration test for encoding package (2) --- .../src/test/resources/encoding.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core-java-modules/{core-java => core-java-string-operations-2}/src/test/resources/encoding.txt (100%) diff --git a/core-java-modules/core-java/src/test/resources/encoding.txt b/core-java-modules/core-java-string-operations-2/src/test/resources/encoding.txt similarity index 100% rename from core-java-modules/core-java/src/test/resources/encoding.txt rename to core-java-modules/core-java-string-operations-2/src/test/resources/encoding.txt From aa5551bd9ba043060b58597bca9086db5d58accc Mon Sep 17 00:00:00 2001 From: GilvanOrnelas Date: Sun, 7 Jun 2020 19:18:58 -0300 Subject: [PATCH 36/46] Spring Import Annotation - initial commit (#9424) Co-authored-by: Gilvan Ornelas Fernandes Filho --- .../animal/AnimalConfiguration.java | 9 +++++ .../animal/AnimalScanConfiguration.java | 9 +++++ .../importannotation/animal/Bird.java | 4 +++ .../importannotation/animal/BirdConfig.java | 13 ++++++++ .../baeldung/importannotation/animal/Bug.java | 7 ++++ .../importannotation/animal/BugConfig.java | 9 +++++ .../baeldung/importannotation/animal/Cat.java | 4 +++ .../importannotation/animal/CatConfig.java | 13 ++++++++ .../baeldung/importannotation/animal/Dog.java | 4 +++ .../importannotation/animal/DogConfig.java | 13 ++++++++ .../animal/MammalConfiguration.java | 9 +++++ .../importannotation/zoo/ZooApplication.java | 11 +++++++ .../animal/AnimalConfigUnitTest.java | 31 +++++++++++++++++ .../animal/BugConfigUnitTest.java | 25 ++++++++++++++ .../animal/ConfigUnitTest.java | 31 +++++++++++++++++ .../animal/MammalConfigUnitTest.java | 33 +++++++++++++++++++ .../zoo/ZooApplicationUnitTest.java | 26 +++++++++++++++ 17 files changed, 251 insertions(+) create mode 100644 spring-core-4/src/main/java/com/baeldung/importannotation/animal/AnimalConfiguration.java create mode 100644 spring-core-4/src/main/java/com/baeldung/importannotation/animal/AnimalScanConfiguration.java create mode 100644 spring-core-4/src/main/java/com/baeldung/importannotation/animal/Bird.java create mode 100644 spring-core-4/src/main/java/com/baeldung/importannotation/animal/BirdConfig.java create mode 100644 spring-core-4/src/main/java/com/baeldung/importannotation/animal/Bug.java create mode 100644 spring-core-4/src/main/java/com/baeldung/importannotation/animal/BugConfig.java create mode 100644 spring-core-4/src/main/java/com/baeldung/importannotation/animal/Cat.java create mode 100644 spring-core-4/src/main/java/com/baeldung/importannotation/animal/CatConfig.java create mode 100644 spring-core-4/src/main/java/com/baeldung/importannotation/animal/Dog.java create mode 100644 spring-core-4/src/main/java/com/baeldung/importannotation/animal/DogConfig.java create mode 100644 spring-core-4/src/main/java/com/baeldung/importannotation/animal/MammalConfiguration.java create mode 100644 spring-core-4/src/main/java/com/baeldung/importannotation/zoo/ZooApplication.java create mode 100644 spring-core-4/src/test/java/com/baeldung/importannotation/animal/AnimalConfigUnitTest.java create mode 100644 spring-core-4/src/test/java/com/baeldung/importannotation/animal/BugConfigUnitTest.java create mode 100644 spring-core-4/src/test/java/com/baeldung/importannotation/animal/ConfigUnitTest.java create mode 100644 spring-core-4/src/test/java/com/baeldung/importannotation/animal/MammalConfigUnitTest.java create mode 100644 spring-core-4/src/test/java/com/baeldung/importannotation/zoo/ZooApplicationUnitTest.java diff --git a/spring-core-4/src/main/java/com/baeldung/importannotation/animal/AnimalConfiguration.java b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/AnimalConfiguration.java new file mode 100644 index 0000000000..94f22788b8 --- /dev/null +++ b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/AnimalConfiguration.java @@ -0,0 +1,9 @@ +package com.baeldung.importannotation.animal; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import({ MammalConfiguration.class, BirdConfig.class }) +class AnimalConfiguration { +} diff --git a/spring-core-4/src/main/java/com/baeldung/importannotation/animal/AnimalScanConfiguration.java b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/AnimalScanConfiguration.java new file mode 100644 index 0000000000..9b4310b6d3 --- /dev/null +++ b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/AnimalScanConfiguration.java @@ -0,0 +1,9 @@ +package com.baeldung.importannotation.animal; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan +public class AnimalScanConfiguration { +} diff --git a/spring-core-4/src/main/java/com/baeldung/importannotation/animal/Bird.java b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/Bird.java new file mode 100644 index 0000000000..a785cf7641 --- /dev/null +++ b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/Bird.java @@ -0,0 +1,4 @@ +package com.baeldung.importannotation.animal; + +class Bird { +} diff --git a/spring-core-4/src/main/java/com/baeldung/importannotation/animal/BirdConfig.java b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/BirdConfig.java new file mode 100644 index 0000000000..c5cefe8b22 --- /dev/null +++ b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/BirdConfig.java @@ -0,0 +1,13 @@ +package com.baeldung.importannotation.animal; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +class BirdConfig { + + @Bean + Bird bird() { + return new Bird(); + } +} diff --git a/spring-core-4/src/main/java/com/baeldung/importannotation/animal/Bug.java b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/Bug.java new file mode 100644 index 0000000000..6abe08e393 --- /dev/null +++ b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/Bug.java @@ -0,0 +1,7 @@ +package com.baeldung.importannotation.animal; + +import org.springframework.stereotype.Component; + +@Component(value = "bug") +class Bug { +} diff --git a/spring-core-4/src/main/java/com/baeldung/importannotation/animal/BugConfig.java b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/BugConfig.java new file mode 100644 index 0000000000..9bea16413a --- /dev/null +++ b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/BugConfig.java @@ -0,0 +1,9 @@ +package com.baeldung.importannotation.animal; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import(Bug.class) +class BugConfig { +} diff --git a/spring-core-4/src/main/java/com/baeldung/importannotation/animal/Cat.java b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/Cat.java new file mode 100644 index 0000000000..7eb36c81ce --- /dev/null +++ b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/Cat.java @@ -0,0 +1,4 @@ +package com.baeldung.importannotation.animal; + +class Cat { +} \ No newline at end of file diff --git a/spring-core-4/src/main/java/com/baeldung/importannotation/animal/CatConfig.java b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/CatConfig.java new file mode 100644 index 0000000000..ebb35ffc11 --- /dev/null +++ b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/CatConfig.java @@ -0,0 +1,13 @@ +package com.baeldung.importannotation.animal; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +class CatConfig { + + @Bean + Cat cat() { + return new Cat(); + } +} diff --git a/spring-core-4/src/main/java/com/baeldung/importannotation/animal/Dog.java b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/Dog.java new file mode 100644 index 0000000000..00374c1bc0 --- /dev/null +++ b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/Dog.java @@ -0,0 +1,4 @@ +package com.baeldung.importannotation.animal; + +class Dog { +} diff --git a/spring-core-4/src/main/java/com/baeldung/importannotation/animal/DogConfig.java b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/DogConfig.java new file mode 100644 index 0000000000..c11ee44623 --- /dev/null +++ b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/DogConfig.java @@ -0,0 +1,13 @@ +package com.baeldung.importannotation.animal; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +class DogConfig { + + @Bean + Dog dog() { + return new Dog(); + } +} diff --git a/spring-core-4/src/main/java/com/baeldung/importannotation/animal/MammalConfiguration.java b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/MammalConfiguration.java new file mode 100644 index 0000000000..3d77ac878c --- /dev/null +++ b/spring-core-4/src/main/java/com/baeldung/importannotation/animal/MammalConfiguration.java @@ -0,0 +1,9 @@ +package com.baeldung.importannotation.animal; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import({ DogConfig.class, CatConfig.class }) +class MammalConfiguration { +} diff --git a/spring-core-4/src/main/java/com/baeldung/importannotation/zoo/ZooApplication.java b/spring-core-4/src/main/java/com/baeldung/importannotation/zoo/ZooApplication.java new file mode 100644 index 0000000000..01aa36a796 --- /dev/null +++ b/spring-core-4/src/main/java/com/baeldung/importannotation/zoo/ZooApplication.java @@ -0,0 +1,11 @@ +package com.baeldung.importannotation.zoo; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import com.baeldung.importannotation.animal.AnimalScanConfiguration; + +@Configuration +@Import(AnimalScanConfiguration.class) +class ZooApplication { +} diff --git a/spring-core-4/src/test/java/com/baeldung/importannotation/animal/AnimalConfigUnitTest.java b/spring-core-4/src/test/java/com/baeldung/importannotation/animal/AnimalConfigUnitTest.java new file mode 100644 index 0000000000..7f4795da25 --- /dev/null +++ b/spring-core-4/src/test/java/com/baeldung/importannotation/animal/AnimalConfigUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.importannotation.animal; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { AnimalConfiguration.class }) +class AnimalConfigUnitTest { + + @Autowired + ApplicationContext context; + + @Test + void givenImportedBeans_whenGettingEach_shallFindOnlyTheImportedBeans() { + assertThatBeanExists("dog", Dog.class); + assertThatBeanExists("cat", Cat.class); + assertThatBeanExists("bird", Cat.class); + } + + private void assertThatBeanExists(String beanName, Class beanClass) { + assertTrue(context.containsBean(beanName)); + assertNotNull(context.getBean(beanClass)); + } +} diff --git a/spring-core-4/src/test/java/com/baeldung/importannotation/animal/BugConfigUnitTest.java b/spring-core-4/src/test/java/com/baeldung/importannotation/animal/BugConfigUnitTest.java new file mode 100644 index 0000000000..2a2e0b332a --- /dev/null +++ b/spring-core-4/src/test/java/com/baeldung/importannotation/animal/BugConfigUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.importannotation.animal; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = BugConfig.class) +class BugConfigUnitTest { + + @Autowired + ApplicationContext context; + + @Test + void givenImportInComponent_whenLookForBean_shallFindIt() { + assertTrue(context.containsBean("bug")); + assertNotNull(context.getBean(Bug.class)); + } +} diff --git a/spring-core-4/src/test/java/com/baeldung/importannotation/animal/ConfigUnitTest.java b/spring-core-4/src/test/java/com/baeldung/importannotation/animal/ConfigUnitTest.java new file mode 100644 index 0000000000..dadd2abae6 --- /dev/null +++ b/spring-core-4/src/test/java/com/baeldung/importannotation/animal/ConfigUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.importannotation.animal; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { BirdConfig.class, CatConfig.class, DogConfig.class }) +class ConfigUnitTest { + + @Autowired + ApplicationContext context; + + @Test + void givenImportedBeans_whenGettingEach_shallFindIt() { + assertThatBeanExists("dog", Dog.class); + assertThatBeanExists("cat", Cat.class); + assertThatBeanExists("bird", Bird.class); + } + + private void assertThatBeanExists(String beanName, Class beanClass) { + assertTrue(context.containsBean(beanName)); + assertNotNull(context.getBean(beanClass)); + } +} diff --git a/spring-core-4/src/test/java/com/baeldung/importannotation/animal/MammalConfigUnitTest.java b/spring-core-4/src/test/java/com/baeldung/importannotation/animal/MammalConfigUnitTest.java new file mode 100644 index 0000000000..5e1596253c --- /dev/null +++ b/spring-core-4/src/test/java/com/baeldung/importannotation/animal/MammalConfigUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.importannotation.animal; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { MammalConfiguration.class }) +class MammalConfigUnitTest { + + @Autowired + ApplicationContext context; + + @Test + void givenImportedBeans_whenGettingEach_shallFindOnlyTheImportedBeans() { + assertThatBeanExists("dog", Dog.class); + assertThatBeanExists("cat", Cat.class); + + assertFalse(context.containsBean("bird")); + } + + private void assertThatBeanExists(String beanName, Class beanClass) { + assertTrue(context.containsBean(beanName)); + assertNotNull(context.getBean(beanClass)); + } +} diff --git a/spring-core-4/src/test/java/com/baeldung/importannotation/zoo/ZooApplicationUnitTest.java b/spring-core-4/src/test/java/com/baeldung/importannotation/zoo/ZooApplicationUnitTest.java new file mode 100644 index 0000000000..e832e27b28 --- /dev/null +++ b/spring-core-4/src/test/java/com/baeldung/importannotation/zoo/ZooApplicationUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.importannotation.zoo; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = ZooApplication.class) +class ZooApplicationUnitTest { + + @Autowired + ApplicationContext context; + + @Test + void givenTheScanInTheAnimalPackage_whenGettingAnyAnimal_shallFindItInTheContext() { + assertNotNull(context.getBean("dog")); + assertNotNull(context.getBean("bird")); + assertNotNull(context.getBean("cat")); + assertNotNull(context.getBean("bug")); + } +} From 2a6533cb96384b2c9aa94a52c66e8d5199263822 Mon Sep 17 00:00:00 2001 From: mikr Date: Mon, 8 Jun 2020 00:22:04 +0200 Subject: [PATCH 37/46] JAVA-101 Split Core Kotlin --- core-kotlin-modules/core-kotlin-2/README.md | 9 ----- .../core-kotlin-collections/README.md | 1 + .../com/baeldung/sorting/SortingExample.kt | 0 .../baeldung/sorting/SortingExampleKtTest.kt | 0 .../core-kotlin-datastructures/README.md | 6 ++++ .../core-kotlin-datastructures/pom.xml | 29 +++++++++++++++ .../kotlin/com/baeldung/binarytree/Main.kt | 0 .../kotlin/com/baeldung/binarytree/Node.kt | 0 .../test/kotlin/com}/binarytree/NodeTest.kt | 2 +- .../core-kotlin-date-time/README.md | 6 ++++ .../core-kotlin-date-time/pom.xml | 36 +++++++++++++++++++ .../baeldung/dates/datetime/UseDuration.kt | 0 .../baeldung/dates/datetime/UseLocalDate.kt | 0 .../dates/datetime/UseLocalDateTime.kt | 0 .../baeldung/dates/datetime/UseLocalTime.kt | 0 .../com/baeldung/dates/datetime/UsePeriod.kt | 0 .../dates/datetime/UseZonedDateTime.kt | 0 .../com/baeldung/dates/CreateDateUnitTest.kt | 0 .../com/baeldung/dates/ExtractDateUnitTest.kt | 0 .../com/baeldung/dates/FormatDateUnitTest.kt | 0 .../com/baeldung/dates/PeriodDateUnitTest.kt | 0 .../datetime/UseLocalDateTimeUnitTest.kt | 0 .../dates/datetime/UseLocalDateUnitTest.kt | 0 .../dates/datetime/UseLocalTimeUnitTest.kt | 0 .../dates/datetime/UsePeriodUnitTest.kt | 0 .../datetime/UseZonedDateTimeUnitTest.kt | 0 .../core-kotlin-design-patterns/README.md | 6 ++++ .../core-kotlin-design-patterns/pom.xml | 29 +++++++++++++++ .../kotlin/com/baeldung/builder/FoodOrder.kt | 0 .../com/baeldung/builder/FoodOrderApply.kt | 0 .../com/baeldung/builder/FoodOrderNamed.kt | 0 .../main/kotlin/com/baeldung/builder/Main.kt | 0 .../builder/BuilderPatternUnitTest.kt | 0 .../core-kotlin-lang-2/README.md | 1 + .../com/baeldung/scope/ScopeFunctions.kt | 0 .../baeldung/scope/ScopeFunctionsUnitTest.kt | 0 .../core-kotlin-testing/README.md | 6 ++++ .../pom.xml | 14 +++++--- .../kotlin/com/baeldung/junit5/Calculator.kt | 0 .../com/baeldung/junit5/CalculatorUnitTest.kt | 0 .../baeldung/junit5/DivideByZeroException.kt | 0 .../com/baeldung/junit5/SimpleUnitTest.kt | 0 core-kotlin-modules/core-kotlin/README.md | 12 ++----- .../nullassertion/NotNullAssertionUnitTest.kt | 0 .../com/baeldung/sequences/SequencesTest.kt | 0 .../baeldung/ternary/TernaryOperatorTest.kt | 0 core-kotlin-modules/pom.xml | 6 ++-- .../kotlin/com/baeldung/gson/GsonUnitTest.kt | 0 48 files changed, 136 insertions(+), 27 deletions(-) delete mode 100644 core-kotlin-modules/core-kotlin-2/README.md rename core-kotlin-modules/{core-kotlin => core-kotlin-collections}/src/main/kotlin/com/baeldung/sorting/SortingExample.kt (100%) rename core-kotlin-modules/{core-kotlin => core-kotlin-collections}/src/test/kotlin/com/baeldung/sorting/SortingExampleKtTest.kt (100%) create mode 100644 core-kotlin-modules/core-kotlin-datastructures/README.md create mode 100644 core-kotlin-modules/core-kotlin-datastructures/pom.xml rename core-kotlin-modules/{core-kotlin => core-kotlin-datastructures}/src/main/kotlin/com/baeldung/binarytree/Main.kt (100%) rename core-kotlin-modules/{core-kotlin => core-kotlin-datastructures}/src/main/kotlin/com/baeldung/binarytree/Node.kt (100%) rename core-kotlin-modules/{core-kotlin/src/test/kotlin/com/baeldung => core-kotlin-datastructures/src/test/kotlin/com}/binarytree/NodeTest.kt (99%) create mode 100644 core-kotlin-modules/core-kotlin-date-time/README.md create mode 100644 core-kotlin-modules/core-kotlin-date-time/pom.xml rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/main/kotlin/com/baeldung/dates/datetime/UseDuration.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDate.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDateTime.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/main/kotlin/com/baeldung/dates/datetime/UseLocalTime.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/main/kotlin/com/baeldung/dates/datetime/UsePeriod.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/main/kotlin/com/baeldung/dates/datetime/UseZonedDateTime.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/test/kotlin/com/baeldung/dates/CreateDateUnitTest.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/test/kotlin/com/baeldung/dates/ExtractDateUnitTest.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/test/kotlin/com/baeldung/dates/FormatDateUnitTest.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/test/kotlin/com/baeldung/dates/PeriodDateUnitTest.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateTimeUnitTest.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateUnitTest.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/test/kotlin/com/baeldung/dates/datetime/UseLocalTimeUnitTest.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/test/kotlin/com/baeldung/dates/datetime/UsePeriodUnitTest.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-date-time}/src/test/kotlin/com/baeldung/dates/datetime/UseZonedDateTimeUnitTest.kt (100%) create mode 100644 core-kotlin-modules/core-kotlin-design-patterns/README.md create mode 100644 core-kotlin-modules/core-kotlin-design-patterns/pom.xml rename core-kotlin-modules/{core-kotlin => core-kotlin-design-patterns}/src/main/kotlin/com/baeldung/builder/FoodOrder.kt (100%) rename core-kotlin-modules/{core-kotlin => core-kotlin-design-patterns}/src/main/kotlin/com/baeldung/builder/FoodOrderApply.kt (100%) rename core-kotlin-modules/{core-kotlin => core-kotlin-design-patterns}/src/main/kotlin/com/baeldung/builder/FoodOrderNamed.kt (100%) rename core-kotlin-modules/{core-kotlin => core-kotlin-design-patterns}/src/main/kotlin/com/baeldung/builder/Main.kt (100%) rename core-kotlin-modules/{core-kotlin => core-kotlin-design-patterns}/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt (100%) rename core-kotlin-modules/{core-kotlin => core-kotlin-lang-2}/src/main/kotlin/com/baeldung/scope/ScopeFunctions.kt (100%) rename core-kotlin-modules/{core-kotlin => core-kotlin-lang-2}/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt (100%) create mode 100644 core-kotlin-modules/core-kotlin-testing/README.md rename core-kotlin-modules/{core-kotlin-2 => core-kotlin-testing}/pom.xml (64%) rename core-kotlin-modules/{core-kotlin => core-kotlin-testing}/src/test/kotlin/com/baeldung/junit5/Calculator.kt (100%) rename core-kotlin-modules/{core-kotlin => core-kotlin-testing}/src/test/kotlin/com/baeldung/junit5/CalculatorUnitTest.kt (100%) rename core-kotlin-modules/{core-kotlin => core-kotlin-testing}/src/test/kotlin/com/baeldung/junit5/DivideByZeroException.kt (100%) rename core-kotlin-modules/{core-kotlin => core-kotlin-testing}/src/test/kotlin/com/baeldung/junit5/SimpleUnitTest.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin}/src/test/kotlin/com/baeldung/nullassertion/NotNullAssertionUnitTest.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin}/src/test/kotlin/com/baeldung/sequences/SequencesTest.kt (100%) rename core-kotlin-modules/{core-kotlin-2 => core-kotlin}/src/test/kotlin/com/baeldung/ternary/TernaryOperatorTest.kt (100%) rename {core-kotlin-modules/core-kotlin => kotlin-libraries-2}/src/test/kotlin/com/baeldung/gson/GsonUnitTest.kt (100%) diff --git a/core-kotlin-modules/core-kotlin-2/README.md b/core-kotlin-modules/core-kotlin-2/README.md deleted file mode 100644 index d6d6b2f706..0000000000 --- a/core-kotlin-modules/core-kotlin-2/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## Core Kotlin 2 - -This module contains articles about Kotlin core features. - -### Relevant articles: -- [Working with Dates in Kotlin](https://www.baeldung.com/kotlin-dates) -- [Kotlin Ternary Conditional Operator](https://www.baeldung.com/kotlin-ternary-operator) -- [Sequences in Kotlin](https://www.baeldung.com/kotlin/sequences) -- [[<-- Prev]](/core-kotlin-modules/core-kotlin) diff --git a/core-kotlin-modules/core-kotlin-collections/README.md b/core-kotlin-modules/core-kotlin-collections/README.md index 66f15e7419..997680c2bc 100644 --- a/core-kotlin-modules/core-kotlin-collections/README.md +++ b/core-kotlin-modules/core-kotlin-collections/README.md @@ -10,3 +10,4 @@ This module contains articles about core Kotlin collections. - [Filtering Kotlin Collections](https://www.baeldung.com/kotlin-filter-collection) - [Collection Transformations in Kotlin](https://www.baeldung.com/kotlin-collection-transformations) - [Difference between fold and reduce in Kotlin](https://www.baeldung.com/kotlin/fold-vs-reduce) +- [Guide to Sorting in Kotlin](https://www.baeldung.com/kotlin-sort) diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/sorting/SortingExample.kt b/core-kotlin-modules/core-kotlin-collections/src/main/kotlin/com/baeldung/sorting/SortingExample.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/sorting/SortingExample.kt rename to core-kotlin-modules/core-kotlin-collections/src/main/kotlin/com/baeldung/sorting/SortingExample.kt diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/sorting/SortingExampleKtTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/sorting/SortingExampleKtTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/sorting/SortingExampleKtTest.kt rename to core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/sorting/SortingExampleKtTest.kt diff --git a/core-kotlin-modules/core-kotlin-datastructures/README.md b/core-kotlin-modules/core-kotlin-datastructures/README.md new file mode 100644 index 0000000000..3b22730a76 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-datastructures/README.md @@ -0,0 +1,6 @@ +## Core Kotlin + +This module contains articles about data structures in Kotlin + +### Relevant articles: +[Implementing a Binary Tree in Kotlin](https://www.baeldung.com/kotlin-binary-tree) diff --git a/core-kotlin-modules/core-kotlin-datastructures/pom.xml b/core-kotlin-modules/core-kotlin-datastructures/pom.xml new file mode 100644 index 0000000000..eae11c17cf --- /dev/null +++ b/core-kotlin-modules/core-kotlin-datastructures/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + core-kotlin-datastructures + core-kotlin-datastructures + jar + + + com.baeldung.core-kotlin-modules + core-kotlin-modules + 1.0.0-SNAPSHOT + + + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + + + 1.1.1 + + + \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/binarytree/Main.kt b/core-kotlin-modules/core-kotlin-datastructures/src/main/kotlin/com/baeldung/binarytree/Main.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/binarytree/Main.kt rename to core-kotlin-modules/core-kotlin-datastructures/src/main/kotlin/com/baeldung/binarytree/Main.kt diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/binarytree/Node.kt b/core-kotlin-modules/core-kotlin-datastructures/src/main/kotlin/com/baeldung/binarytree/Node.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/binarytree/Node.kt rename to core-kotlin-modules/core-kotlin-datastructures/src/main/kotlin/com/baeldung/binarytree/Node.kt diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/binarytree/NodeTest.kt b/core-kotlin-modules/core-kotlin-datastructures/src/test/kotlin/com/binarytree/NodeTest.kt similarity index 99% rename from core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/binarytree/NodeTest.kt rename to core-kotlin-modules/core-kotlin-datastructures/src/test/kotlin/com/binarytree/NodeTest.kt index 9414d7dde9..5a7f7fc50f 100644 --- a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/binarytree/NodeTest.kt +++ b/core-kotlin-modules/core-kotlin-datastructures/src/test/kotlin/com/binarytree/NodeTest.kt @@ -1,4 +1,4 @@ -package com.baeldung.binarytree +package com.binarytree import org.junit.After import org.junit.Assert.assertEquals diff --git a/core-kotlin-modules/core-kotlin-date-time/README.md b/core-kotlin-modules/core-kotlin-date-time/README.md new file mode 100644 index 0000000000..a3e358d4e3 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-date-time/README.md @@ -0,0 +1,6 @@ +## Core Kotlin Date and Time + +This module contains articles about Kotlin core date/time features. + +### Relevant articles: +[Working with Dates in Kotlin](https://www.baeldung.com/kotlin-dates) diff --git a/core-kotlin-modules/core-kotlin-date-time/pom.xml b/core-kotlin-modules/core-kotlin-date-time/pom.xml new file mode 100644 index 0000000000..f3cacefc19 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-date-time/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + core-kotlin-date-time + core-kotlin-date-time + jar + + + com.baeldung.core-kotlin-modules + core-kotlin-modules + 1.0.0-SNAPSHOT + + + + + org.assertj + assertj-core + ${org.assertj.core.version} + test + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + + + 1.1.1 + 3.9.0 + + + \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-2/src/main/kotlin/com/baeldung/dates/datetime/UseDuration.kt b/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseDuration.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/main/kotlin/com/baeldung/dates/datetime/UseDuration.kt rename to core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseDuration.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDate.kt b/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDate.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDate.kt rename to core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDate.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDateTime.kt b/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDateTime.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDateTime.kt rename to core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDateTime.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/main/kotlin/com/baeldung/dates/datetime/UseLocalTime.kt b/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalTime.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/main/kotlin/com/baeldung/dates/datetime/UseLocalTime.kt rename to core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalTime.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/main/kotlin/com/baeldung/dates/datetime/UsePeriod.kt b/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UsePeriod.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/main/kotlin/com/baeldung/dates/datetime/UsePeriod.kt rename to core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UsePeriod.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/main/kotlin/com/baeldung/dates/datetime/UseZonedDateTime.kt b/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseZonedDateTime.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/main/kotlin/com/baeldung/dates/datetime/UseZonedDateTime.kt rename to core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseZonedDateTime.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/CreateDateUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/CreateDateUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/CreateDateUnitTest.kt rename to core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/CreateDateUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/ExtractDateUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/ExtractDateUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/ExtractDateUnitTest.kt rename to core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/ExtractDateUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/FormatDateUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/FormatDateUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/FormatDateUnitTest.kt rename to core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/FormatDateUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/PeriodDateUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/PeriodDateUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/PeriodDateUnitTest.kt rename to core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/PeriodDateUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateTimeUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateTimeUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateTimeUnitTest.kt rename to core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateTimeUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateUnitTest.kt rename to core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/datetime/UseLocalTimeUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalTimeUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/datetime/UseLocalTimeUnitTest.kt rename to core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalTimeUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/datetime/UsePeriodUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UsePeriodUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/datetime/UsePeriodUnitTest.kt rename to core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UsePeriodUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/datetime/UseZonedDateTimeUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseZonedDateTimeUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/dates/datetime/UseZonedDateTimeUnitTest.kt rename to core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseZonedDateTimeUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-design-patterns/README.md b/core-kotlin-modules/core-kotlin-design-patterns/README.md new file mode 100644 index 0000000000..4bdc164a47 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-design-patterns/README.md @@ -0,0 +1,6 @@ +## Core Kotlin Design Patterns + +This module contains articles about design patterns in Kotlin + +### Relevant articles: +- [Creational Design Patterns in Kotlin: Builder](https://www.baeldung.com/kotlin-builder-pattern) diff --git a/core-kotlin-modules/core-kotlin-design-patterns/pom.xml b/core-kotlin-modules/core-kotlin-design-patterns/pom.xml new file mode 100644 index 0000000000..c112602bc2 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-design-patterns/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + core-kotlin-design-patterns + core-kotlin-design-patterns + jar + + + com.baeldung.core-kotlin-modules + core-kotlin-modules + 1.0.0-SNAPSHOT + + + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + + + 1.1.1 + + + \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/builder/FoodOrder.kt b/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrder.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/builder/FoodOrder.kt rename to core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrder.kt diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/builder/FoodOrderApply.kt b/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrderApply.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/builder/FoodOrderApply.kt rename to core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrderApply.kt diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/builder/FoodOrderNamed.kt b/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrderNamed.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/builder/FoodOrderNamed.kt rename to core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrderNamed.kt diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/builder/Main.kt b/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/Main.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/builder/Main.kt rename to core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/Main.kt diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt b/core-kotlin-modules/core-kotlin-design-patterns/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt rename to core-kotlin-modules/core-kotlin-design-patterns/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-lang-2/README.md b/core-kotlin-modules/core-kotlin-lang-2/README.md index e64a39cb9b..76d490226f 100644 --- a/core-kotlin-modules/core-kotlin-lang-2/README.md +++ b/core-kotlin-modules/core-kotlin-lang-2/README.md @@ -10,4 +10,5 @@ This module contains articles about core features in the Kotlin language. - [Initializing Arrays in Kotlin](https://www.baeldung.com/kotlin-initialize-array) - [Lazy Initialization in Kotlin](https://www.baeldung.com/kotlin-lazy-initialization) - [Comprehensive Guide to Null Safety in Kotlin](https://www.baeldung.com/kotlin-null-safety) +- [Kotlin Scope Functions](https://www.baeldung.com/kotlin-scope-functions) - [[<-- Prev]](/core-kotlin-modules/core-kotlin-lang) diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/scope/ScopeFunctions.kt b/core-kotlin-modules/core-kotlin-lang-2/src/main/kotlin/com/baeldung/scope/ScopeFunctions.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/scope/ScopeFunctions.kt rename to core-kotlin-modules/core-kotlin-lang-2/src/main/kotlin/com/baeldung/scope/ScopeFunctions.kt diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt rename to core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-testing/README.md b/core-kotlin-modules/core-kotlin-testing/README.md new file mode 100644 index 0000000000..f4d89593a7 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-testing/README.md @@ -0,0 +1,6 @@ +## Core Kotlin Testing + +This module contains articles about testing in Kotlin + +### Relevant articles: +- [JUnit 5 for Kotlin Developers](https://www.baeldung.com/junit-5-kotlin) \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-2/pom.xml b/core-kotlin-modules/core-kotlin-testing/pom.xml similarity index 64% rename from core-kotlin-modules/core-kotlin-2/pom.xml rename to core-kotlin-modules/core-kotlin-testing/pom.xml index ae6e2d175a..d38bc62409 100644 --- a/core-kotlin-modules/core-kotlin-2/pom.xml +++ b/core-kotlin-modules/core-kotlin-testing/pom.xml @@ -3,8 +3,8 @@ 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 - core-kotlin-2 - core-kotlin-2 + core-kotlin-testing + core-kotlin-testing jar @@ -15,11 +15,15 @@ - org.assertj - assertj-core - ${assertj.version} + org.junit.platform + junit-platform-runner + ${junit.platform.version} test + + 1.1.1 + + \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/junit5/Calculator.kt b/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/Calculator.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/junit5/Calculator.kt rename to core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/Calculator.kt diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/junit5/CalculatorUnitTest.kt b/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/CalculatorUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/junit5/CalculatorUnitTest.kt rename to core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/CalculatorUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/junit5/DivideByZeroException.kt b/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/DivideByZeroException.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/junit5/DivideByZeroException.kt rename to core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/DivideByZeroException.kt diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/junit5/SimpleUnitTest.kt b/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/SimpleUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/junit5/SimpleUnitTest.kt rename to core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/SimpleUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin/README.md b/core-kotlin-modules/core-kotlin/README.md index 90caccf5c8..48d19c987a 100644 --- a/core-kotlin-modules/core-kotlin/README.md +++ b/core-kotlin-modules/core-kotlin/README.md @@ -7,13 +7,5 @@ This module contains articles about Kotlin core features. - [Kotlin Java Interoperability](https://www.baeldung.com/kotlin-java-interoperability) - [Get a Random Number in Kotlin](https://www.baeldung.com/kotlin-random-number) - [Create a Java and Kotlin Project with Maven](https://www.baeldung.com/kotlin-maven-java-project) -- [Guide to Sorting in Kotlin](https://www.baeldung.com/kotlin-sort) -- [Creational Design Patterns in Kotlin: Builder](https://www.baeldung.com/kotlin-builder-pattern) -- [Kotlin Scope Functions](https://www.baeldung.com/kotlin-scope-functions) -- [Implementing a Binary Tree in Kotlin](https://www.baeldung.com/kotlin-binary-tree) -- [JUnit 5 for Kotlin Developers](https://www.baeldung.com/junit-5-kotlin) -- [Converting Kotlin Data Class from JSON using GSON](https://www.baeldung.com/kotlin-json-convert-data-class) -- [Fuel HTTP Library with Kotlin](https://www.baeldung.com/kotlin-fuel) -- [Introduction to Kovenant Library for Kotlin](https://www.baeldung.com/kotlin-kovenant) -- [Dependency Injection for Kotlin with Injekt](https://www.baeldung.com/kotlin-dependency-injection-with-injekt) -- [[More --> ]](/core-kotlin-modules/core-kotlin-2) +- [Kotlin Ternary Conditional Operator](https://www.baeldung.com/kotlin-ternary-operator) +- [Sequences in Kotlin](https://www.baeldung.com/kotlin/sequences) diff --git a/core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/nullassertion/NotNullAssertionUnitTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/nullassertion/NotNullAssertionUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/nullassertion/NotNullAssertionUnitTest.kt rename to core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/nullassertion/NotNullAssertionUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/sequences/SequencesTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/sequences/SequencesTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/sequences/SequencesTest.kt rename to core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/sequences/SequencesTest.kt diff --git a/core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/ternary/TernaryOperatorTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/ternary/TernaryOperatorTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin-2/src/test/kotlin/com/baeldung/ternary/TernaryOperatorTest.kt rename to core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/ternary/TernaryOperatorTest.kt diff --git a/core-kotlin-modules/pom.xml b/core-kotlin-modules/pom.xml index de41aecf73..8b626e1c1b 100644 --- a/core-kotlin-modules/pom.xml +++ b/core-kotlin-modules/pom.xml @@ -18,17 +18,19 @@ core-kotlin - core-kotlin-2 core-kotlin-advanced core-kotlin-annotations core-kotlin-collections core-kotlin-concurrency + core-kotlin-date-time + core-kotlin-design-patterns core-kotlin-io core-kotlin-lang core-kotlin-lang-2 - core-kotlin-strings core-kotlin-lang-oop core-kotlin-lang-oop-2 + core-kotlin-strings + core-kotlin-testing diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/gson/GsonUnitTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/gson/GsonUnitTest.kt similarity index 100% rename from core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/gson/GsonUnitTest.kt rename to kotlin-libraries-2/src/test/kotlin/com/baeldung/gson/GsonUnitTest.kt From 694261868d0eab7d9e4271e7b32bb107adbf896b Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Mon, 8 Jun 2020 12:59:01 +0530 Subject: [PATCH 38/46] JAVA-931: Migrate spring-cloud-connectors-heroku to parent-boot-2 --- .../spring-cloud-connectors-heroku/pom.xml | 14 ++++++++++---- .../connectors/heroku/book/BookController.java | 4 +++- .../cloud/connectors/heroku/book/BookService.java | 6 ++++-- .../heroku/product/ProductController.java | 4 +++- .../connectors/heroku/product/ProductService.java | 6 ++++-- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/spring-cloud/spring-cloud-connectors-heroku/pom.xml b/spring-cloud/spring-cloud-connectors-heroku/pom.xml index 1dad3ddcb7..c09a282197 100644 --- a/spring-cloud/spring-cloud-connectors-heroku/pom.xml +++ b/spring-cloud/spring-cloud-connectors-heroku/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../../parent-boot-1 + ../../parent-boot-2 @@ -35,6 +35,11 @@ org.postgresql postgresql + + net.bytebuddy + byte-buddy-dep + ${bytebuddy.version} + com.h2database h2 @@ -55,8 +60,9 @@ - Brixton.SR7 - 9.4-1201-jdbc4 + Hoxton.SR4 + 42.2.10 + 1.10.10 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/book/BookController.java b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/book/BookController.java index eb2972f35a..f998059028 100644 --- a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/book/BookController.java +++ b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/book/BookController.java @@ -1,5 +1,7 @@ package com.baeldung.spring.cloud.connectors.heroku.book; +import java.util.Optional; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -15,7 +17,7 @@ public class BookController { } @GetMapping("/{bookId}") - public Book findBook(@PathVariable Long bookId) { + public Optional findBook(@PathVariable Long bookId) { return bookService.findBookById(bookId); } diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/book/BookService.java b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/book/BookService.java index 4978ded65f..a83dfe64b7 100644 --- a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/book/BookService.java +++ b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/book/BookService.java @@ -1,5 +1,7 @@ package com.baeldung.spring.cloud.connectors.heroku.book; +import java.util.Optional; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; @@ -15,8 +17,8 @@ public class BookService { this.bookRepository = bookRepository; } - public Book findBookById(Long bookId) { - return bookRepository.findOne(bookId); + public Optional findBookById(Long bookId) { + return bookRepository.findById(bookId); } @Transactional(propagation = Propagation.REQUIRED) diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductController.java b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductController.java index 51cf4412bf..7875c712f9 100644 --- a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductController.java +++ b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductController.java @@ -1,5 +1,7 @@ package com.baeldung.spring.cloud.connectors.heroku.product; +import java.util.Optional; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -15,7 +17,7 @@ public class ProductController { } @GetMapping("/{productId}") - public Product findProduct(@PathVariable Long productId) { + public Optional findProduct(@PathVariable Long productId) { return productService.findProductById(productId); } diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductService.java b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductService.java index f25b4ecf7b..bdd13e9863 100644 --- a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductService.java +++ b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductService.java @@ -1,5 +1,7 @@ package com.baeldung.spring.cloud.connectors.heroku.product; +import java.util.Optional; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; @@ -15,8 +17,8 @@ public class ProductService { this.productRepository = productRepository; } - public Product findProductById(Long productId) { - return productRepository.findOne(productId); + public Optional findProductById(Long productId) { + return productRepository.findById(productId); } @Transactional(propagation = Propagation.REQUIRED) From c098ffa7e940490889261bf9e4918848ea12f92f Mon Sep 17 00:00:00 2001 From: Cristian Rosu Date: Mon, 8 Jun 2020 15:01:46 +0300 Subject: [PATCH 39/46] BAEL-4070: updated test names and parameter ordering + moved code to spring-boot-properties-2 --- .../lists/ListsPropertiesUnitTest.java | 34 +++++++++---------- .../SpringListPropertiesApplication.java | 0 .../src/test/resources/lists.properties | 0 3 files changed, 17 insertions(+), 17 deletions(-) rename spring-boot-modules/{spring-boot-properties => spring-boot-properties-2}/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java (61%) rename spring-boot-modules/{spring-boot-properties => spring-boot-properties-2}/src/test/java/com/baeldung/properties/lists/SpringListPropertiesApplication.java (100%) rename spring-boot-modules/{spring-boot-properties => spring-boot-properties-2}/src/test/resources/lists.properties (100%) diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java b/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java similarity index 61% rename from spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java rename to spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java index 80cb8e9ea0..60ba4cc108 100644 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java +++ b/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java @@ -46,43 +46,43 @@ public class ListsPropertiesUnitTest { private Environment environment; @Test - public void whenContextIsInitialized_ThenInjectedArrayContainsExpectedValues() { - assertEquals(arrayOfStrings, new String[] {"Baeldung", "dot", "com"}); + public void whenContextIsInitialized_thenInjectedArrayContainsExpectedValues() { + assertEquals(new String[] {"Baeldung", "dot", "com"}, arrayOfStrings); } @Test - public void whenContextIsInitialized_ThenInjectedListContainsUnexpectedValues() { - assertEquals(unexpectedListOfStrings, Collections.singletonList("Baeldung,dot,com")); + public void whenContextIsInitialized_thenInjectedListContainsUnexpectedValues() { + assertEquals(Collections.singletonList("Baeldung,dot,com"), unexpectedListOfStrings); } @Test - public void whenContextIsInitialized_ThenInjectedListContainsExpectedValues() { - assertEquals(listOfStrings, Arrays.asList("Baeldung", "dot", "com")); + public void whenContextIsInitialized_thenInjectedListContainsExpectedValues() { + assertEquals(Arrays.asList("Baeldung", "dot", "com"), listOfStrings); } @Test - public void whenContextIsInitialized_ThenInjectedListV2ContainsExpectedValues() { - assertEquals(listOfStringsV2, Arrays.asList("Baeldung", "dot", "com")); + public void whenContextIsInitialized_thenInjectedListV2ContainsExpectedValues() { + assertEquals(Arrays.asList("Baeldung", "dot", "com"), listOfStringsV2); } @Test - public void whenContextIsInitialized_ThenInjectedListWithCustomDelimiterContainsExpectedValues() { - assertEquals(listOfStringsWithCustomDelimiter, Arrays.asList("Baeldung", "dot", "com")); + public void whenContextIsInitialized_thenInjectedListWithCustomDelimiterContainsExpectedValues() { + assertEquals(Arrays.asList("Baeldung", "dot", "com"), listOfStringsWithCustomDelimiter); } @Test - public void whenContextIsInitialized_ThenInjectedListOfBasicTypesContainsExpectedValues() { - assertEquals(listOfBooleans, Arrays.asList(false, false, true)); - assertEquals(listOfIntegers, Arrays.asList(1, 2, 3, 4)); - assertEquals(listOfCharacters, Arrays.asList('a', 'b', 'c')); + public void whenContextIsInitialized_thenInjectedListOfBasicTypesContainsExpectedValues() { + assertEquals(Arrays.asList(false, false, true), listOfBooleans); + assertEquals(Arrays.asList(1, 2, 3, 4), listOfIntegers); + assertEquals(Arrays.asList('a', 'b', 'c'), listOfCharacters); } @Test - public void whenReadingFromSpringEnvironment_ThenPropertiesHaveExpectedValues() { + public void whenReadingFromSpringEnvironment_thenPropertiesHaveExpectedValues() { String[] arrayOfStrings = environment.getProperty("arrayOfStrings", String[].class); List listOfStrings = (List)environment.getProperty("arrayOfStrings", List.class); - assertEquals(arrayOfStrings, new String[] {"Baeldung", "dot", "com"}); - assertEquals(listOfStrings, Arrays.asList("Baeldung", "dot", "com")); + assertEquals(new String[] {"Baeldung", "dot", "com"}, arrayOfStrings); + assertEquals(Arrays.asList("Baeldung", "dot", "com"), listOfStrings); } } diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/SpringListPropertiesApplication.java b/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/lists/SpringListPropertiesApplication.java similarity index 100% rename from spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/lists/SpringListPropertiesApplication.java rename to spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/lists/SpringListPropertiesApplication.java diff --git a/spring-boot-modules/spring-boot-properties/src/test/resources/lists.properties b/spring-boot-modules/spring-boot-properties-2/src/test/resources/lists.properties similarity index 100% rename from spring-boot-modules/spring-boot-properties/src/test/resources/lists.properties rename to spring-boot-modules/spring-boot-properties-2/src/test/resources/lists.properties From facf0c3929d7140880a14b18434e83fc6ca6b749 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Mon, 8 Jun 2020 18:22:26 +0530 Subject: [PATCH 40/46] JAVA-936: Migrate spring-cloud-task to parent-boot-2 --- spring-cloud/spring-cloud-task/pom.xml | 8 ++++---- .../spring-cloud-task/springcloudtaskbatch/pom.xml | 8 ++++++++ .../src/test/resources/application.yml | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/spring-cloud/spring-cloud-task/pom.xml b/spring-cloud/spring-cloud-task/pom.xml index 377d16a999..e2006ee9d3 100644 --- a/spring-cloud/spring-cloud-task/pom.xml +++ b/spring-cloud/spring-cloud-task/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../../parent-boot-1 + ../../parent-boot-2 @@ -40,8 +40,8 @@ - Brixton.SR7 - 1.2.2.RELEASE + Hoxton.SR4 + 2.2.3.RELEASE diff --git a/spring-cloud/spring-cloud-task/springcloudtaskbatch/pom.xml b/spring-cloud/spring-cloud-task/springcloudtaskbatch/pom.xml index fd10322efb..4e6b8b8b6c 100644 --- a/spring-cloud/spring-cloud-task/springcloudtaskbatch/pom.xml +++ b/spring-cloud/spring-cloud-task/springcloudtaskbatch/pom.xml @@ -45,6 +45,13 @@ org.springframework.cloud spring-cloud-task-batch + + + net.bytebuddy + byte-buddy-dep + ${bytebuddy.version} + + com.h2database h2 @@ -63,6 +70,7 @@ com.baeldung.TaskDemo + 1.10.10 diff --git a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/resources/application.yml b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/resources/application.yml index 794ac4d247..8a6e4fc172 100644 --- a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/resources/application.yml +++ b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/resources/application.yml @@ -1,6 +1,6 @@ spring: datasource: - url: jdbc:h2:mem:springcloud + url: jdbc:h2:mem:springcloud;DB_CLOSE_ON_EXIT=FALSE username: sa password: jpa: From db295e33871b7f2d7f728e472a62ef87405bc093 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Mon, 8 Jun 2020 18:33:45 +0530 Subject: [PATCH 41/46] JAVA-936: Migrate spring-cloud-task to parent-boot-2 --- spring-cloud/spring-cloud-task/springcloudtasksink/pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spring-cloud/spring-cloud-task/springcloudtasksink/pom.xml b/spring-cloud/spring-cloud-task/springcloudtasksink/pom.xml index 93255959e4..33f6ccde74 100644 --- a/spring-cloud/spring-cloud-task/springcloudtasksink/pom.xml +++ b/spring-cloud/spring-cloud-task/springcloudtasksink/pom.xml @@ -50,8 +50,7 @@ - 1.2.2.RELEASE - 1.3.0.RELEASE + 2.3.1.RELEASE From 32259e7caf765879ac2a9eba2ab6c39f03ef2908 Mon Sep 17 00:00:00 2001 From: Amit Pandey Date: Tue, 9 Jun 2020 00:26:31 +0530 Subject: [PATCH 42/46] Java 1687 1 (#9450) * used password encoder over plaintext password * used password encoder over plaintext password --- .../loginextrafieldscustom/CustomUserRepository.java | 9 ++++++++- .../baeldung/loginextrafieldscustom/SecurityConfig.java | 2 ++ .../baeldung/loginextrafieldssimple/SecurityConfig.java | 2 ++ .../loginextrafieldssimple/SimpleUserRepository.java | 9 ++++++++- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserRepository.java b/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserRepository.java index 428c8bf532..effc750940 100644 --- a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserRepository.java +++ b/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserRepository.java @@ -5,11 +5,18 @@ import java.util.Collection; import org.apache.commons.lang3.StringUtils; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Repository; @Repository("userRepository") public class CustomUserRepository implements UserRepository { + private PasswordEncoder passwordEncoder; + + public CustomUserRepository(PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + } + @Override public User findUser(String username, String domain) { if (StringUtils.isAnyBlank(username, domain)) { @@ -17,7 +24,7 @@ public class CustomUserRepository implements UserRepository { } else { Collection authorities = new ArrayList<>(); User user = new User(username, domain, - "$2a$10$U3GhSMpsMSOE8Kqsbn58/edxDBKlVuYMh7qk/7ErApYFjJzi2VG5K", true, + passwordEncoder.encode("secret"), true, true, true, true, authorities); return user; } diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/SecurityConfig.java b/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/SecurityConfig.java index def85ab978..88380f1ed6 100644 --- a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/SecurityConfig.java +++ b/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/SecurityConfig.java @@ -1,6 +1,7 @@ package com.baeldung.loginextrafieldscustom; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; @@ -56,6 +57,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { return new SimpleUrlAuthenticationFailureHandler("/login?error=true"); } + @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SecurityConfig.java b/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SecurityConfig.java index d8c5ea8147..48ca53c0b2 100644 --- a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SecurityConfig.java +++ b/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SecurityConfig.java @@ -1,6 +1,7 @@ package com.baeldung.loginextrafieldssimple; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; @@ -59,6 +60,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { return new SimpleUrlAuthenticationFailureHandler("/login?error=true"); } + @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleUserRepository.java b/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleUserRepository.java index e8aaa774a1..44929c6189 100644 --- a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleUserRepository.java +++ b/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleUserRepository.java @@ -5,11 +5,18 @@ import java.util.Collection; import org.apache.commons.lang3.StringUtils; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Repository; @Repository("userRepository") public class SimpleUserRepository implements UserRepository { + private PasswordEncoder passwordEncoder; + + public SimpleUserRepository(PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + } + @Override public User findUser(String username, String domain) { if (StringUtils.isAnyBlank(username, domain)) { @@ -17,7 +24,7 @@ public class SimpleUserRepository implements UserRepository { } else { Collection authorities = new ArrayList<>(); User user = new User(username, domain, - "$2a$10$U3GhSMpsMSOE8Kqsbn58/edxDBKlVuYMh7qk/7ErApYFjJzi2VG5K", true, + passwordEncoder.encode("secret"), true, true, true, true, authorities); return user; } From 8076eebbf8e40e659879a96fc2cacf3bd3b19e0d Mon Sep 17 00:00:00 2001 From: KevinGilmore Date: Mon, 8 Jun 2020 17:59:52 -0500 Subject: [PATCH 43/46] Bael 4082 - update README (#9465) * BAEL-3336 BAEL-3058 add links * BAEL-3319: add link * BAEL-3284: add link * BAEL-3198: add link to article * BAEL-3479: add link to article * BAEL-3485: add article link * SCALA-38: move to new package and add link back to article * SCALA-38: add imports back into unit test * BAEL-3908: add link back to article * BAEL-2893 BAEL-3927 add link back to article * BAEL-4082: add link back to article --- spring-core-4/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-core-4/README.md b/spring-core-4/README.md index 592f4cd011..11a966f23d 100644 --- a/spring-core-4/README.md +++ b/spring-core-4/README.md @@ -6,4 +6,5 @@ This module contains articles about core Spring functionality - [Creating Spring Beans Through Factory Methods](https://www.baeldung.com/spring-beans-factory-methods) - [How to dynamically Autowire a Bean in Spring](https://www.baeldung.com/spring-dynamic-autowire) +- [Spring @Import Annotation](https://www.baeldung.com/spring-import-annotation) - More articles: [[<-- prev]](/spring-core-3) From c387fe5dd604120243e131636533839dc7c8212b Mon Sep 17 00:00:00 2001 From: kwoyke Date: Tue, 9 Jun 2020 21:44:45 +0200 Subject: [PATCH 44/46] BAEL-3979: Get rid of the Spring Snapshots & Milestones repos (#9434) --- .../spring-boot-kotlin/pom.xml | 38 ++----------------- .../repository/ProductRepository.kt | 7 ++-- .../repository/ProductRepositoryCoroutines.kt | 7 ++-- 3 files changed, 9 insertions(+), 43 deletions(-) diff --git a/spring-boot-modules/spring-boot-kotlin/pom.xml b/spring-boot-modules/spring-boot-kotlin/pom.xml index 79d62645da..7ee048546a 100644 --- a/spring-boot-modules/spring-boot-kotlin/pom.xml +++ b/spring-boot-modules/spring-boot-kotlin/pom.xml @@ -14,38 +14,6 @@ ../../parent-kotlin - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - - org.jetbrains.kotlin @@ -142,9 +110,9 @@ 1.3.31 - 1.0.0.M1 - 1.0.0.M7 - 1.0.0.BUILD-SNAPSHOT + 1.0.0.RELEASE + 0.8.2.RELEASE + 0.8.4.RELEASE 1.2.1 diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepository.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepository.kt index 20c3827c26..64ffd014ad 100644 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepository.kt +++ b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepository.kt @@ -1,7 +1,7 @@ package com.baeldung.nonblockingcoroutines.repository import com.baeldung.nonblockingcoroutines.model.Product -import org.springframework.data.r2dbc.function.DatabaseClient +import org.springframework.data.r2dbc.core.DatabaseClient import org.springframework.stereotype.Repository import reactor.core.publisher.Flux import reactor.core.publisher.Mono @@ -10,7 +10,7 @@ import reactor.core.publisher.Mono class ProductRepository(private val client: DatabaseClient) { fun getProductById(id: Int): Mono { - return client.execute().sql("SELECT * FROM products WHERE id = $1") + return client.execute("SELECT * FROM products WHERE id = $1") .bind(0, id) .`as`(Product::class.java) .fetch() @@ -18,8 +18,7 @@ class ProductRepository(private val client: DatabaseClient) { } fun addNewProduct(name: String, price: Float): Mono { - return client.execute() - .sql("INSERT INTO products (name, price) VALUES($1, $2)") + return client.execute("INSERT INTO products (name, price) VALUES($1, $2)") .bind(0, name) .bind(1, price) .then() diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepositoryCoroutines.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepositoryCoroutines.kt index 60a19d4d00..f2667ec033 100644 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepositoryCoroutines.kt +++ b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepositoryCoroutines.kt @@ -6,14 +6,14 @@ import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.reactive.awaitFirstOrNull import kotlinx.coroutines.reactive.flow.asFlow -import org.springframework.data.r2dbc.function.DatabaseClient +import org.springframework.data.r2dbc.core.DatabaseClient import org.springframework.stereotype.Repository @Repository class ProductRepositoryCoroutines(private val client: DatabaseClient) { suspend fun getProductById(id: Int): Product? = - client.execute().sql("SELECT * FROM products WHERE id = $1") + client.execute("SELECT * FROM products WHERE id = $1") .bind(0, id) .`as`(Product::class.java) .fetch() @@ -21,8 +21,7 @@ class ProductRepositoryCoroutines(private val client: DatabaseClient) { .awaitFirstOrNull() suspend fun addNewProduct(name: String, price: Float) = - client.execute() - .sql("INSERT INTO products (name, price) VALUES($1, $2)") + client.execute("INSERT INTO products (name, price) VALUES($1, $2)") .bind(0, name) .bind(1, price) .then() From 26c11b3e85981879f8248b5bdfb89a88f352e17d Mon Sep 17 00:00:00 2001 From: Mihai238 Date: Tue, 9 Jun 2020 21:49:03 +0200 Subject: [PATCH 45/46] add example for security with profiles (#9185) Co-authored-by: Mihai Lepadat --- .../baeldung/securityprofile/Application.java | 14 ++++++++++ .../ApplicationNoSecurity.java | 17 +++++++++++ .../securityprofile/ApplicationSecurity.java | 16 +++++++++++ .../securityprofile/EmployeeController.java | 16 +++++++++++ .../EmployeeControllerNoSecurityUnitTest.java | 28 +++++++++++++++++++ .../EmployeeControllerUnitTest.java | 28 +++++++++++++++++++ 6 files changed, 119 insertions(+) create mode 100644 spring-5-security/src/main/java/com/baeldung/securityprofile/Application.java create mode 100644 spring-5-security/src/main/java/com/baeldung/securityprofile/ApplicationNoSecurity.java create mode 100644 spring-5-security/src/main/java/com/baeldung/securityprofile/ApplicationSecurity.java create mode 100644 spring-5-security/src/main/java/com/baeldung/securityprofile/EmployeeController.java create mode 100644 spring-5-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerNoSecurityUnitTest.java create mode 100644 spring-5-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerUnitTest.java diff --git a/spring-5-security/src/main/java/com/baeldung/securityprofile/Application.java b/spring-5-security/src/main/java/com/baeldung/securityprofile/Application.java new file mode 100644 index 0000000000..5f17227777 --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/securityprofile/Application.java @@ -0,0 +1,14 @@ +package com.baeldung.securityprofile; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; + +@SpringBootApplication +@EnableWebSecurity +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/spring-5-security/src/main/java/com/baeldung/securityprofile/ApplicationNoSecurity.java b/spring-5-security/src/main/java/com/baeldung/securityprofile/ApplicationNoSecurity.java new file mode 100644 index 0000000000..c899eb9268 --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/securityprofile/ApplicationNoSecurity.java @@ -0,0 +1,17 @@ +package com.baeldung.securityprofile; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@Profile("test") +public class ApplicationNoSecurity extends WebSecurityConfigurerAdapter { + + @Override + public void configure(WebSecurity web) { + web.ignoring().antMatchers("/**"); + } + +} diff --git a/spring-5-security/src/main/java/com/baeldung/securityprofile/ApplicationSecurity.java b/spring-5-security/src/main/java/com/baeldung/securityprofile/ApplicationSecurity.java new file mode 100644 index 0000000000..51a8d6aa11 --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/securityprofile/ApplicationSecurity.java @@ -0,0 +1,16 @@ +package com.baeldung.securityprofile; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@Profile("prod") +public class ApplicationSecurity extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().authenticated(); + } +} diff --git a/spring-5-security/src/main/java/com/baeldung/securityprofile/EmployeeController.java b/spring-5-security/src/main/java/com/baeldung/securityprofile/EmployeeController.java new file mode 100644 index 0000000000..a28a5129ca --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/securityprofile/EmployeeController.java @@ -0,0 +1,16 @@ +package com.baeldung.securityprofile; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.List; + +@RestController +public class EmployeeController { + + @GetMapping("/employees") + public List getEmployees() { + return Collections.singletonList("Adam Johnson"); + } +} diff --git a/spring-5-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerNoSecurityUnitTest.java b/spring-5-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerNoSecurityUnitTest.java new file mode 100644 index 0000000000..7112392412 --- /dev/null +++ b/spring-5-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerNoSecurityUnitTest.java @@ -0,0 +1,28 @@ +package com.baeldung.securityprofile; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@WebMvcTest(value = EmployeeController.class) +@ActiveProfiles("test") +public class EmployeeControllerNoSecurityUnitTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenSecurityDisabled_shouldBeOk() throws Exception { + this.mockMvc.perform(get("/employees")) + .andExpect(status().isOk()); + } + +} \ No newline at end of file diff --git a/spring-5-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerUnitTest.java b/spring-5-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerUnitTest.java new file mode 100644 index 0000000000..b8c8b79eb5 --- /dev/null +++ b/spring-5-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerUnitTest.java @@ -0,0 +1,28 @@ +package com.baeldung.securityprofile; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@WebMvcTest(value = EmployeeController.class) +@ActiveProfiles("prod") +public class EmployeeControllerUnitTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenSecurityEnabled_shouldBeForbidden() throws Exception { + this.mockMvc.perform(get("/employees")) + .andExpect(status().isForbidden()); + } + +} \ No newline at end of file From bb2d9b400ebc9f918fb3d3f3e82ced4b50ac13b2 Mon Sep 17 00:00:00 2001 From: Greg Martin Date: Tue, 9 Jun 2020 16:03:05 -0400 Subject: [PATCH 46/46] Moved Thymeleaf code into it's own package. --- .../com/baeldung/{pdf => pdfthymeleaf}/PDFThymeleafExample.java | 2 +- .../baeldung/{pdf => pdfthymeleaf}/PDFThymeleafUnitTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename pdf/src/main/java/com/baeldung/{pdf => pdfthymeleaf}/PDFThymeleafExample.java (97%) rename pdf/src/test/java/com/baeldung/{pdf => pdfthymeleaf}/PDFThymeleafUnitTest.java (98%) diff --git a/pdf/src/main/java/com/baeldung/pdf/PDFThymeleafExample.java b/pdf/src/main/java/com/baeldung/pdfthymeleaf/PDFThymeleafExample.java similarity index 97% rename from pdf/src/main/java/com/baeldung/pdf/PDFThymeleafExample.java rename to pdf/src/main/java/com/baeldung/pdfthymeleaf/PDFThymeleafExample.java index 2e1df1d320..28879b8958 100644 --- a/pdf/src/main/java/com/baeldung/pdf/PDFThymeleafExample.java +++ b/pdf/src/main/java/com/baeldung/pdfthymeleaf/PDFThymeleafExample.java @@ -1,4 +1,4 @@ -package com.baeldung.pdf; +package com.baeldung.pdfthymeleaf; import com.lowagie.text.DocumentException; import org.thymeleaf.TemplateEngine; diff --git a/pdf/src/test/java/com/baeldung/pdf/PDFThymeleafUnitTest.java b/pdf/src/test/java/com/baeldung/pdfthymeleaf/PDFThymeleafUnitTest.java similarity index 98% rename from pdf/src/test/java/com/baeldung/pdf/PDFThymeleafUnitTest.java rename to pdf/src/test/java/com/baeldung/pdfthymeleaf/PDFThymeleafUnitTest.java index e253dce06c..75d38fbf22 100644 --- a/pdf/src/test/java/com/baeldung/pdf/PDFThymeleafUnitTest.java +++ b/pdf/src/test/java/com/baeldung/pdfthymeleaf/PDFThymeleafUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.pdf; +package com.baeldung.pdfthymeleaf; import com.lowagie.text.DocumentException; import org.junit.Test;