diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy new file mode 100644 index 0000000000..eb4d1f7f87 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy @@ -0,0 +1,3 @@ +package com.baeldung + +class Car implements VehicleTrait {} \ No newline at end of file diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy index 3f1e694f17..0d395bffcd 100644 --- a/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy +++ b/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy @@ -22,7 +22,7 @@ trait UserTrait implements Human { msg } - def whoAmI() { + def self() { return this } diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy new file mode 100644 index 0000000000..f5ae8fab30 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy @@ -0,0 +1,9 @@ +package com.baeldung + +trait VehicleTrait extends WheelTrait { + + String showWheels() { + return "Num of Wheels $noOfWheels" + } + +} \ No newline at end of file diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy new file mode 100644 index 0000000000..364d5b883e --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy @@ -0,0 +1,7 @@ +package com.baeldung + +trait WheelTrait { + + int noOfWheels + +} \ No newline at end of file diff --git a/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy new file mode 100644 index 0000000000..97ffc50c76 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy @@ -0,0 +1,85 @@ +package com.baeldung.map + +import static org.junit.Assert.* +import org.junit.Test + +class MapUnitTest { + + @Test + void whenUsingEach_thenMapIsIterated() { + def map = [ + 'FF0000' : 'Red', + '00FF00' : 'Lime', + '0000FF' : 'Blue', + 'FFFF00' : 'Yellow' + ] + + map.each { println "Hex Code: $it.key = Color Name: $it.value" } + } + + @Test + void whenUsingEachWithEntry_thenMapIsIterated() { + def map = [ + 'E6E6FA' : 'Lavender', + 'D8BFD8' : 'Thistle', + 'DDA0DD' : 'Plum', + ] + + map.each { entry -> println "Hex Code: $entry.key = Color Name: $entry.value" } + } + + @Test + void whenUsingEachWithKeyAndValue_thenMapIsIterated() { + def map = [ + '000000' : 'Black', + 'FFFFFF' : 'White', + '808080' : 'Gray' + ] + + map.each { key, val -> + println "Hex Code: $key = Color Name $val" + } + } + + @Test + void whenUsingEachWithIndexAndEntry_thenMapIsIterated() { + def map = [ + '800080' : 'Purple', + '4B0082' : 'Indigo', + '6A5ACD' : 'Slate Blue' + ] + + map.eachWithIndex { entry, index -> + def indent = ((index == 0 || index % 2 == 0) ? " " : "") + println "$indent Hex Code: $entry.key = Color Name: $entry.value" + } + } + + @Test + void whenUsingEachWithIndexAndKeyAndValue_thenMapIsIterated() { + def map = [ + 'FFA07A' : 'Light Salmon', + 'FF7F50' : 'Coral', + 'FF6347' : 'Tomato', + 'FF4500' : 'Orange Red' + ] + + map.eachWithIndex { key, val, index -> + def indent = ((index == 0 || index % 2 == 0) ? " " : "") + println "$indent Hex Code: $key = Color Name: $val" + } + } + + @Test + void whenUsingForLoop_thenMapIsIterated() { + def map = [ + '2E8B57' : 'Seagreen', + '228B22' : 'Forest Green', + '008000' : 'Green' + ] + + for (entry in map) { + println "Hex Code: $entry.key = Color Name: $entry.value" + } + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy index 0c74a9be62..85130e8f07 100644 --- a/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy +++ b/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy @@ -57,7 +57,7 @@ class TraitsUnitTest extends Specification { def 'Should return employee instance when using Employee.whoAmI method' () { when: - def emp = employee.whoAmI() + def emp = employee.self() then: emp emp instanceof Employee diff --git a/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java b/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java new file mode 100644 index 0000000000..0b1dd952dc --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java @@ -0,0 +1,62 @@ +package com.baeldung.streamreduce.application; + +import com.baeldung.streamreduce.entities.User; +import com.baeldung.streamreduce.utilities.NumberUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Application { + + public static void main(String[] args) { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + int result1 = numbers.stream().reduce(0, (a, b) -> a + b); + System.out.println(result1); + + int result2 = numbers.stream().reduce(0, Integer::sum); + System.out.println(result2); + + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result3 = letters.stream().reduce("", (a, b) -> a + b); + System.out.println(result3); + + String result4 = letters.stream().reduce("", String::concat); + System.out.println(result4); + + String result5 = letters.stream().reduce("", (a, b) -> a.toUpperCase() + b.toUpperCase()); + System.out.println(result5); + + List users = Arrays.asList(new User("John", 30), new User("Julie", 35)); + int result6 = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + System.out.println(result6); + + String result7 = letters.parallelStream().reduce("", String::concat); + System.out.println(result7); + + int result8 = users.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + System.out.println(result8); + + List userList = new ArrayList<>(); + for (int i = 0; i <= 1000000; i++) { + userList.add(new User("John" + i, i)); + } + + long t1 = System.currentTimeMillis(); + int result9 = userList.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + long t2 = System.currentTimeMillis(); + System.out.println(result9); + System.out.println("Sequential stream time: " + (t2 - t1) + "ms"); + + long t3 = System.currentTimeMillis(); + int result10 = userList.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + long t4 = System.currentTimeMillis(); + System.out.println(result10); + System.out.println("Parallel stream time: " + (t4 - t3) + "ms"); + + int result11 = NumberUtils.divideListElements(numbers, 1); + System.out.println(result11); + + int result12 = NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 0); + System.out.println(result12); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/streamreduce/entities/User.java b/core-java-8/src/main/java/com/baeldung/streamreduce/entities/User.java new file mode 100644 index 0000000000..bc13a8cde6 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/streamreduce/entities/User.java @@ -0,0 +1,25 @@ +package com.baeldung.streamreduce.entities; + +public class User { + + private final String name; + private final int age; + + public User(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + @Override + public String toString() { + return "User{" + "name=" + name + ", age=" + age + '}'; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/streamreduce/utilities/NumberUtils.java b/core-java-8/src/main/java/com/baeldung/streamreduce/utilities/NumberUtils.java new file mode 100644 index 0000000000..7a6a85e6c4 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/streamreduce/utilities/NumberUtils.java @@ -0,0 +1,52 @@ +package com.baeldung.streamreduce.utilities; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.logging.Level; +import java.util.logging.Logger; + +public abstract class NumberUtils { + + private static final Logger LOGGER = Logger.getLogger(NumberUtils.class.getName()); + + public static int divideListElements(List values, Integer divider) { + return values.stream() + .reduce(0, (a, b) -> { + try { + return a / divider + b / divider; + } catch (ArithmeticException e) { + LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero"); + } + return 0; + }); + } + + public static int divideListElementsWithExtractedTryCatchBlock(List values, int divider) { + return values.stream().reduce(0, (a, b) -> divide(a, divider) + divide(b, divider)); + } + + public static int divideListElementsWithApplyFunctionMethod(List values, int divider) { + BiFunction division = (a, b) -> a / b; + return values.stream().reduce(0, (a, b) -> applyFunction(division, a, divider) + applyFunction(division, b, divider)); + } + + private static int divide(int value, int factor) { + int result = 0; + try { + result = value / factor; + } catch (ArithmeticException e) { + LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero"); + } + return result; + } + + private static int applyFunction(BiFunction function, int a, int b) { + try { + return function.apply(a, b); + } + catch(Exception e) { + LOGGER.log(Level.INFO, "Exception occurred!"); + } + return 0; + } +} diff --git a/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceManualTest.java b/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceManualTest.java new file mode 100644 index 0000000000..9222cbb689 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceManualTest.java @@ -0,0 +1,126 @@ +package com.baeldung.streamreduce.tests; + +import com.baeldung.streamreduce.entities.User; +import com.baeldung.streamreduce.utilities.NumberUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class StreamReduceManualTest { + + @Test + public void givenIntegerList_whenReduceWithSumAccumulatorLambda_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + + int result = numbers.stream().reduce(0, (a, b) -> a + b); + + assertThat(result).isEqualTo(21); + } + + @Test + public void givenIntegerList_whenReduceWithSumAccumulatorMethodReference_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + + int result = numbers.stream().reduce(0, Integer::sum); + + assertThat(result).isEqualTo(21); + } + + @Test + public void givenStringList_whenReduceWithConcatenatorAccumulatorLambda_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + + String result = letters.stream().reduce("", (a, b) -> a + b); + + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenStringList_whenReduceWithConcatenatorAccumulatorMethodReference_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + + String result = letters.stream().reduce("", String::concat); + + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenStringList_whenReduceWithUppercaseConcatenatorAccumulator_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + + String result = letters.stream().reduce("", (a, b) -> a.toUpperCase() + b.toUpperCase()); + + assertThat(result).isEqualTo("ABCDE"); + } + + @Test + public void givenUserList_whenReduceWithAgeAccumulatorAndSumCombiner_thenCorrect() { + List users = Arrays.asList(new User("John", 30), new User("Julie", 35)); + + int result = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + + assertThat(result).isEqualTo(65); + } + + @Test + public void givenStringList_whenReduceWithParallelStream_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + + String result = letters.parallelStream().reduce("", String::concat); + + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElements_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + + assertThat(NumberUtils.divideListElements(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlock_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + + assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlockAndListContainsZero_thenCorrect() { + List numbers = Arrays.asList(0, 1, 2, 3, 4, 5, 6); + + assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlockAndDividerIsZero_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + + assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 0)).isEqualTo(0); + } + + @Test + public void givenStream_whneCalleddivideListElementsWithApplyFunctionMethod_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + + assertThat(NumberUtils.divideListElementsWithApplyFunctionMethod(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenTwoStreams_whenCalledReduceOnParallelizedStream_thenFasterExecutionTime() { + List userList = new ArrayList<>(); + for (int i = 0; i <= 1000000; i++) { + userList.add(new User("John" + i, i)); + } + long currentTime1 = System.currentTimeMillis(); + userList.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + long sequentialExecutionTime = System.currentTimeMillis() -currentTime1; + long currentTime2 = System.currentTimeMillis(); + userList.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + long parallelizedExecutionTime = System.currentTimeMillis() - currentTime2; + + assertThat(parallelizedExecutionTime).isLessThan(sequentialExecutionTime); + } +} diff --git a/core-java-collections-list/README.md b/core-java-collections-list/README.md index d1112047ba..3a4a7c69e8 100644 --- a/core-java-collections-list/README.md +++ b/core-java-collections-list/README.md @@ -27,3 +27,4 @@ - [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections) - [Intersection of Two Lists in Java](https://www.baeldung.com/java-lists-intersection) - [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist) +- [Determine If All Elements Are the Same in a Java List](https://www.baeldung.com/java-list-all-equal) diff --git a/core-java-collections-list/pom.xml b/core-java-collections-list/pom.xml index 737be8ee34..b9b6f4a6a6 100644 --- a/core-java-collections-list/pom.xml +++ b/core-java-collections-list/pom.xml @@ -52,6 +52,17 @@ colt ${colt.version} + + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-core.version} + diff --git a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java new file mode 100644 index 0000000000..bd37e5e74e --- /dev/null +++ b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java @@ -0,0 +1,96 @@ +package com.baeldung.list.primitive; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import gnu.trove.list.array.TIntArrayList; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Measurement(batchSize = 100000, iterations = 10) +@Warmup(batchSize = 100000, iterations = 10) +@State(Scope.Thread) +public class PrimitivesListPerformance { + + private List arrayList = new ArrayList<>(); + private TIntArrayList tList = new TIntArrayList(); + private cern.colt.list.IntArrayList coltList = new cern.colt.list.IntArrayList(); + private IntArrayList fastUtilList = new IntArrayList(); + + private int getValue = 10; + + @Benchmark + public boolean addArrayList() { + return arrayList.add(getValue); + } + + @Benchmark + public boolean addTroveIntList() { + return tList.add(getValue); + } + + @Benchmark + public void addColtIntList() { + coltList.add(getValue); + } + + @Benchmark + public boolean addFastUtilIntList() { + return fastUtilList.add(getValue); + } + + @Benchmark + public int getArrayList() { + return arrayList.get(getValue); + } + + @Benchmark + public int getTroveIntList() { + return tList.get(getValue); + } + + @Benchmark + public int getColtIntList() { + return coltList.get(getValue); + } + + @Benchmark + public int getFastUtilIntList() { + return fastUtilList.getInt(getValue); + } + + @Benchmark + public boolean containsArrayList() { + return arrayList.contains(getValue); + } + + @Benchmark + public boolean containsTroveIntList() { + return tList.contains(getValue); + } + + @Benchmark + public boolean containsColtIntList() { + return coltList.contains(getValue); + } + + @Benchmark + public boolean containsFastUtilIntList() { + return fastUtilList.contains(getValue); + } + + public static void main(String[] args) throws Exception { + Options options = new OptionsBuilder() + .include(PrimitivesListPerformance.class.getSimpleName()).threads(1) + .forks(1).shouldFailOnError(true) + .shouldDoGC(true) + .jvmArgs("-server").build(); + new Runner(options).run(); + } +} diff --git a/ddd/pom.xml b/ddd/pom.xml index 749e444e52..4ac65ea841 100644 --- a/ddd/pom.xml +++ b/ddd/pom.xml @@ -9,10 +9,10 @@ DDD series examples - org.springframework.boot - spring-boot-starter-parent - 2.0.6.RELEASE - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 @@ -86,6 +86,7 @@ 1.0.1 2.22.0 + 2.0.6.RELEASE \ No newline at end of file diff --git a/ddd/src/test/java/com/baeldung/ddd/order/OrderTest.java b/ddd/src/test/java/com/baeldung/ddd/order/OrderUnitTest.java similarity index 99% rename from ddd/src/test/java/com/baeldung/ddd/order/OrderTest.java rename to ddd/src/test/java/com/baeldung/ddd/order/OrderUnitTest.java index 431a6a5293..502827960a 100644 --- a/ddd/src/test/java/com/baeldung/ddd/order/OrderTest.java +++ b/ddd/src/test/java/com/baeldung/ddd/order/OrderUnitTest.java @@ -11,7 +11,7 @@ import org.joda.money.Money; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -class OrderTest { +class OrderUnitTest { @DisplayName("given order with two items, when calculate total cost, then sum is returned") @Test void test0() throws Exception { diff --git a/ddd/src/test/java/com/baeldung/ddd/order/jpa/ViolateOrderBusinessRulesTest.java b/ddd/src/test/java/com/baeldung/ddd/order/jpa/ViolateOrderBusinessRulesUnitTest.java similarity index 96% rename from ddd/src/test/java/com/baeldung/ddd/order/jpa/ViolateOrderBusinessRulesTest.java rename to ddd/src/test/java/com/baeldung/ddd/order/jpa/ViolateOrderBusinessRulesUnitTest.java index 3eda9250f9..6f1de3276c 100644 --- a/ddd/src/test/java/com/baeldung/ddd/order/jpa/ViolateOrderBusinessRulesTest.java +++ b/ddd/src/test/java/com/baeldung/ddd/order/jpa/ViolateOrderBusinessRulesUnitTest.java @@ -7,7 +7,7 @@ import java.math.BigDecimal; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -public class ViolateOrderBusinessRulesTest { +public class ViolateOrderBusinessRulesUnitTest { @DisplayName("given two non-zero order line items, when create an order with them, it's possible to set total cost to zero") @Test void test() throws Exception { diff --git a/gson/src/test/java/org/baeldung/gson/conversion/JsonObjectConversionsUnitTest.java b/gson/src/test/java/org/baeldung/gson/conversion/JsonObjectConversionsUnitTest.java new file mode 100644 index 0000000000..847ec1b85d --- /dev/null +++ b/gson/src/test/java/org/baeldung/gson/conversion/JsonObjectConversionsUnitTest.java @@ -0,0 +1,33 @@ +package org.baeldung.gson.conversion; + +import com.google.gson.*; +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +public class JsonObjectConversionsUnitTest { + + @Test + void whenUsingJsonParser_thenConvertToJsonObject() throws Exception { + // Example 1: Using JsonParser + String json = "{ \"name\": \"Baeldung\", \"java\": true }"; + + JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject(); + + Assert.assertTrue(jsonObject.isJsonObject()); + Assert.assertTrue(jsonObject.get("name").getAsString().equals("Baeldung")); + Assert.assertTrue(jsonObject.get("java").getAsBoolean() == true); + } + + @Test + void whenUsingGsonInstanceFromJson_thenConvertToJsonObject() throws Exception { + // Example 2: Using fromJson + String json = "{ \"name\": \"Baeldung\", \"java\": true }"; + + JsonObject convertedObject = new Gson().fromJson(json, JsonObject.class); + + Assert.assertTrue(convertedObject.isJsonObject()); + Assert.assertTrue(convertedObject.get("name").getAsString().equals("Baeldung")); + Assert.assertTrue(convertedObject.get("java").getAsBoolean() == true); + } + +} diff --git a/guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerTest.java b/guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerUnitTest.java similarity index 97% rename from guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerTest.java rename to guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerUnitTest.java index 2711a77ebd..9808546e82 100644 --- a/guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerTest.java +++ b/guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerUnitTest.java @@ -21,7 +21,7 @@ import com.stackify.Application; @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) @WebAppConfiguration -public class EmployeeControllerTest { +public class EmployeeControllerUnitTest { private static final String CONTENT_TYPE = "application/json;charset=UTF-8"; diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java b/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java new file mode 100644 index 0000000000..985851f456 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java @@ -0,0 +1,33 @@ +package com.baeldung.jackson.dtos; + +public class Address { + + String streetNumber; + String streetName; + String city; + + public String getStreetNumber() { + return streetNumber; + } + + public void setStreetNumber(String streetNumber) { + this.streetNumber = streetNumber; + } + + public String getStreetName() { + return streetName; + } + + public void setStreetName(String streetName) { + this.streetName = streetName; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java b/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java new file mode 100644 index 0000000000..13093cdcad --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java @@ -0,0 +1,47 @@ +package com.baeldung.jackson.dtos; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; + +@JacksonXmlRootElement(localName = "person") +public final class Person { + private String firstName; + private String lastName; + private List phoneNumbers = new ArrayList<>(); + private List
address = new ArrayList<>(); + + public List
getAddress() { + return address; + } + + public void setAddress(List
address) { + this.address = address; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public List getPhoneNumbers() { + return phoneNumbers; + } + + public void setPhoneNumbers(List phoneNumbers) { + this.phoneNumbers = phoneNumbers; + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java index 0e2a52e75c..1d430e9758 100644 --- a/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java @@ -2,19 +2,25 @@ package com.baeldung.jackson.xml; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; import org.junit.Test; +import com.baeldung.jackson.dtos.Address; +import com.baeldung.jackson.dtos.Person; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.dataformat.xml.XmlMapper; -import com.fasterxml.jackson.annotation.JsonProperty; public class XMLSerializeDeserializeUnitTest { @@ -49,24 +55,76 @@ public class XMLSerializeDeserializeUnitTest { assertTrue(value.getX() == 1 && value.getY() == 2); } - @Test + @Test public void whenJavaGotFromXmlStrWithCapitalElem_thenCorrect() throws IOException { XmlMapper xmlMapper = new XmlMapper(); - SimpleBeanForCapitalizedFields value = xmlMapper. - readValue("12", - SimpleBeanForCapitalizedFields.class); + SimpleBeanForCapitalizedFields value = xmlMapper.readValue("12", SimpleBeanForCapitalizedFields.class); assertTrue(value.getX() == 1 && value.getY() == 2); } @Test public void whenJavaSerializedToXmlFileWithCapitalizedField_thenCorrect() throws IOException { XmlMapper xmlMapper = new XmlMapper(); - xmlMapper.writeValue(new File("target/simple_bean_capitalized.xml"), - new SimpleBeanForCapitalizedFields()); + xmlMapper.writeValue(new File("target/simple_bean_capitalized.xml"), new SimpleBeanForCapitalizedFields()); File file = new File("target/simple_bean_capitalized.xml"); assertNotNull(file); } + @Test + public void whenJavaDeserializedFromXmlFile_thenCorrect() throws IOException { + XmlMapper xmlMapper = new XmlMapper(); + + String xml = "RohanDaye99110347319911033478
1Name1City1
2Name2City2
"; + Person value = xmlMapper.readValue(xml, Person.class); + + assertTrue(value.getAddress() + .get(0) + .getCity() + .equalsIgnoreCase("city1") + && value.getAddress() + .get(1) + .getCity() + .equalsIgnoreCase("city2")); + } + + @Test + public void whenJavaSerializedToXmlFile_thenSuccess() throws IOException { + XmlMapper xmlMapper = new XmlMapper(); + + String expectedXml = "RohanDaye99110347319911033478
1Name1City1
2Name2City2
"; + + Person person = new Person(); + + person.setFirstName("Rohan"); + person.setLastName("Daye"); + + List ph = new ArrayList<>(); + ph.add("9911034731"); + ph.add("9911033478"); + person.setPhoneNumbers(ph); + + List
addresses = new ArrayList<>(); + + Address address1 = new Address(); + address1.setStreetNumber("1"); + address1.setStreetName("Name1"); + address1.setCity("City1"); + + Address address2 = new Address(); + address2.setStreetNumber("2"); + address2.setStreetName("Name2"); + address2.setCity("City2"); + + addresses.add(address1); + addresses.add(address2); + + person.setAddress(addresses); + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + xmlMapper.writeValue(byteArrayOutputStream, person); + assertEquals(expectedXml, byteArrayOutputStream.toString()); + } + private static String inputStreamToString(InputStream is) throws IOException { BufferedReader br; StringBuilder sb = new StringBuilder(); @@ -103,10 +161,10 @@ class SimpleBean { } -class SimpleBeanForCapitalizedFields { - @JsonProperty("X") - private int x = 1; - private int y = 2; +class SimpleBeanForCapitalizedFields { + @JsonProperty("X") + private int x = 1; + private int y = 2; public int getX() { return x; diff --git a/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java index b02b67f685..b3aaf8925f 100644 --- a/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java +++ b/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java @@ -9,8 +9,10 @@ import java.util.Arrays; import java.util.Collection; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.apache.commons.collections4.MultiMapUtils; +import org.apache.commons.collections4.MultiSet; import org.apache.commons.collections4.MultiValuedMap; import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.apache.commons.collections4.multimap.HashSetValuedHashMap; @@ -65,25 +67,28 @@ public class MultiValuedMapUnitTest { @Test public void givenMultiValuesMap_whenUsingKeysMethod_thenReturningAllKeys() { MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); map.put("fruits", "orange"); map.put("vehicles", "car"); map.put("vehicles", "bike"); - assertThat(((Collection) map.keys())).contains("fruits", "vehicles"); + MultiSet keys = map.keys(); + + assertThat((keys)).contains("fruits", "vehicles"); + } @Test public void givenMultiValuesMap_whenUsingKeySetMethod_thenReturningAllKeys() { MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); map.put("fruits", "orange"); map.put("vehicles", "car"); map.put("vehicles", "bike"); - assertThat((Collection) map.keySet()).contains("fruits", "vehicles"); + Set keys = map.keySet(); + + assertThat(keys).contains("fruits", "vehicles"); } diff --git a/json/pom.xml b/json/pom.xml index 23955e5a75..7a6d57c28e 100644 --- a/json/pom.xml +++ b/json/pom.xml @@ -73,6 +73,12 @@ ${commons-collections4.version} test + + org.assertj + assertj-core + ${assertj-core.version} + test + @@ -86,6 +92,7 @@ 2.9.7 4.12 1.1.2 + 3.11.1 diff --git a/json/src/main/java/com/baeldung/jsonobject/iterate/JSONObjectIterator.java b/json/src/main/java/com/baeldung/jsonobject/iterate/JSONObjectIterator.java new file mode 100644 index 0000000000..0ff8650652 --- /dev/null +++ b/json/src/main/java/com/baeldung/jsonobject/iterate/JSONObjectIterator.java @@ -0,0 +1,50 @@ +package com.baeldung.jsonobject.iterate; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; + +public class JSONObjectIterator { + + private Map keyValuePairs; + + public JSONObjectIterator() { + keyValuePairs = new HashMap<>(); + } + + public void handleValue(String key, Object value) { + if (value instanceof JSONArray) { + handleJSONArray(key, (JSONArray) value); + } else if (value instanceof JSONObject) { + handleJSONObject((JSONObject) value); + } + keyValuePairs.put(key, value); + } + + public void handleJSONObject(JSONObject jsonObject) { + Iterator jsonObjectIterator = jsonObject.keys(); + jsonObjectIterator.forEachRemaining(key -> { + Object value = jsonObject.get(key); + handleValue(key, value); + }); + } + + public void handleJSONArray(String key, JSONArray jsonArray) { + Iterator jsonArrayIterator = jsonArray.iterator(); + jsonArrayIterator.forEachRemaining(element -> { + handleValue(key, element); + }); + } + + public Map getKeyValuePairs() { + return keyValuePairs; + } + + public void setKeyValuePairs(Map keyValuePairs) { + this.keyValuePairs = keyValuePairs; + } + +} diff --git a/json/src/test/java/com/baeldung/jsonobject/iterate/JSONObjectIteratorUnitTest.java b/json/src/test/java/com/baeldung/jsonobject/iterate/JSONObjectIteratorUnitTest.java new file mode 100644 index 0000000000..55cfdab53b --- /dev/null +++ b/json/src/test/java/com/baeldung/jsonobject/iterate/JSONObjectIteratorUnitTest.java @@ -0,0 +1,79 @@ +package com.baeldung.jsonobject.iterate; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Test; + +public class JSONObjectIteratorUnitTest { + + private JSONObjectIterator jsonObjectIterator = new JSONObjectIterator(); + + @Test + public void givenJSONObject_whenIterating_thenGetKeyValuePairs() { + JSONObject jsonObject = getJsonObject(); + + jsonObjectIterator.handleJSONObject(jsonObject); + + Map keyValuePairs = jsonObjectIterator.getKeyValuePairs(); + assertThat(keyValuePairs.get("rType")).isEqualTo("Regular"); + assertThat(keyValuePairs.get("rId")).isEqualTo("1001"); + assertThat(keyValuePairs.get("cType")).isEqualTo("Chocolate"); + assertThat(keyValuePairs.get("cId")).isEqualTo("1002"); + assertThat(keyValuePairs.get("bType")).isEqualTo("BlueBerry"); + assertThat(keyValuePairs.get("bId")).isEqualTo("1003"); + assertThat(keyValuePairs.get("name")).isEqualTo("Cake"); + assertThat(keyValuePairs.get("cakeId")).isEqualTo("0001"); + assertThat(keyValuePairs.get("type")).isEqualTo("donut"); + assertThat(keyValuePairs.get("Type")).isEqualTo("Maple"); + assertThat(keyValuePairs.get("tId")).isEqualTo("5001"); + assertThat(keyValuePairs.get("batters") + .toString()).isEqualTo("[{\"rType\":\"Regular\",\"rId\":\"1001\"},{\"cType\":\"Chocolate\",\"cId\":\"1002\"},{\"bType\":\"BlueBerry\",\"bId\":\"1003\"}]"); + assertThat(keyValuePairs.get("cakeShapes") + .toString()).isEqualTo("[\"square\",\"circle\",\"heart\"]"); + assertThat(keyValuePairs.get("topping") + .toString()).isEqualTo("{\"Type\":\"Maple\",\"tId\":\"5001\"}"); + } + + private JSONObject getJsonObject() { + JSONObject cake = new JSONObject(); + cake.put("cakeId", "0001"); + cake.put("type", "donut"); + cake.put("name", "Cake"); + + JSONArray batters = new JSONArray(); + JSONObject regular = new JSONObject(); + regular.put("rId", "1001"); + regular.put("rType", "Regular"); + batters.put(regular); + JSONObject chocolate = new JSONObject(); + chocolate.put("cId", "1002"); + chocolate.put("cType", "Chocolate"); + batters.put(chocolate); + JSONObject blueberry = new JSONObject(); + blueberry.put("bId", "1003"); + blueberry.put("bType", "BlueBerry"); + batters.put(blueberry); + + JSONArray cakeShapes = new JSONArray(); + cakeShapes.put("square"); + cakeShapes.put("circle"); + cakeShapes.put("heart"); + + cake.put("cakeShapes", cakeShapes); + + cake.put("batters", batters); + + JSONObject topping = new JSONObject(); + topping.put("tId", "5001"); + topping.put("Type", "Maple"); + + cake.put("topping", topping); + + return cake; + } + +} diff --git a/jta/pom.xml b/jta/pom.xml index 038f1dc8d1..6a31733996 100644 --- a/jta/pom.xml +++ b/jta/pom.xml @@ -10,10 +10,10 @@ JEE JTA demo - org.springframework.boot - spring-boot-starter-parent - 2.0.4.RELEASE - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 @@ -85,5 +85,6 @@ UTF-8 1.8 2.4.1 + 2.0.4.RELEASE diff --git a/libraries/pom.xml b/libraries/pom.xml index d067525315..a6ff9e6a80 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -223,6 +223,12 @@ serenity-spring ${serenity.version} test + + + org.springframework + spring-test + + net.serenity-bdd @@ -318,6 +324,12 @@ pact-jvm-consumer-junit_2.11 ${pact.version} test + + + org.codehaus.groovy + groovy-all + + org.codehaus.groovy @@ -675,6 +687,17 @@ ${mockftpserver.version} test + + org.asciidoctor + asciidoctor-maven-plugin + 1.5.7.1 + + + + org.reflections + reflections + ${reflections.version} + @@ -687,10 +710,6 @@ bintray http://dl.bintray.com/cuba-platform/main - - Apache Staging - https://repository.apache.org/content/groups/staging - nm-repo Numerical Method's Maven Repository @@ -734,7 +753,7 @@ JDO ${basedir}/datanucleus.properties ${basedir}/log4j.properties - true + false false @@ -897,6 +916,8 @@ 1.1.0 2.7.1 3.6 + 0.9.11 + diff --git a/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java b/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java index 9f53f3d25b..bee947df12 100644 --- a/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java +++ b/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java @@ -6,7 +6,7 @@ import org.derive4j.Make; @Data(value = @Derive( inClass = "{ClassName}Impl", - make = {Make.lazyConstructor, Make.constructors} + make = {Make.lazyConstructor, Make.constructors, Make.getters} )) public interface LazyRequest { interface Cases{ diff --git a/libraries/src/main/java/com/baeldung/reflections/ReflectionsApp.java b/libraries/src/main/java/com/baeldung/reflections/ReflectionsApp.java new file mode 100644 index 0000000000..30da8ea837 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/reflections/ReflectionsApp.java @@ -0,0 +1,71 @@ +package com.baeldung.reflections; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.Date; +import java.util.Set; +import java.util.regex.Pattern; + +import org.reflections.Reflections; +import org.reflections.scanners.MethodAnnotationsScanner; +import org.reflections.scanners.MethodParameterScanner; +import org.reflections.scanners.ResourcesScanner; +import org.reflections.scanners.Scanner; +import org.reflections.scanners.SubTypesScanner; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; + +public class ReflectionsApp { + + public Set> getReflectionsSubTypes() { + Reflections reflections = new Reflections("org.reflections"); + Set> scannersSet = reflections.getSubTypesOf(Scanner.class); + return scannersSet; + } + + public Set> getJDKFunctinalInterfaces() { + Reflections reflections = new Reflections("java.util.function"); + Set> typesSet = reflections.getTypesAnnotatedWith(FunctionalInterface.class); + return typesSet; + } + + public Set getDateDeprecatedMethods() { + Reflections reflections = new Reflections(java.util.Date.class, new MethodAnnotationsScanner()); + Set deprecatedMethodsSet = reflections.getMethodsAnnotatedWith(Deprecated.class); + return deprecatedMethodsSet; + } + + @SuppressWarnings("rawtypes") + public Set getDateDeprecatedConstructors() { + Reflections reflections = new Reflections(java.util.Date.class, new MethodAnnotationsScanner()); + Set constructorsSet = reflections.getConstructorsAnnotatedWith(Deprecated.class); + return constructorsSet; + } + + public Set getMethodsWithDateParam() { + Reflections reflections = new Reflections(java.text.SimpleDateFormat.class, new MethodParameterScanner()); + Set methodsSet = reflections.getMethodsMatchParams(Date.class); + return methodsSet; + } + + public Set getMethodsWithVoidReturn() { + Reflections reflections = new Reflections(java.text.SimpleDateFormat.class, new MethodParameterScanner()); + Set methodsSet = reflections.getMethodsReturn(void.class); + return methodsSet; + } + + public Set getPomXmlPaths() { + Reflections reflections = new Reflections(new ResourcesScanner()); + Set resourcesSet = reflections.getResources(Pattern.compile(".*pom\\.xml")); + return resourcesSet; + } + + public Set> getReflectionsSubTypesUsingBuilder() { + Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage("org.reflections")) + .setScanners(new SubTypesScanner())); + + Set> scannersSet = reflections.getSubTypesOf(Scanner.class); + return scannersSet; + } + +} diff --git a/libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsIntegrationTest.java b/libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsLiveTest.java similarity index 99% rename from libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsIntegrationTest.java rename to libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsLiveTest.java index ba1861937b..358b3390f9 100644 --- a/libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsIntegrationTest.java +++ b/libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsLiveTest.java @@ -26,7 +26,7 @@ import com.google.api.services.sheets.v4.model.ValueRange; import static org.assertj.core.api.Assertions.*; -public class GoogleSheetsIntegrationTest { +public class GoogleSheetsLiveTest { private static Sheets sheetsService; diff --git a/libraries/src/test/java/com/baeldung/reflections/ReflectionsUnitTest.java b/libraries/src/test/java/com/baeldung/reflections/ReflectionsUnitTest.java new file mode 100644 index 0000000000..9a3ef0747b --- /dev/null +++ b/libraries/src/test/java/com/baeldung/reflections/ReflectionsUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.reflections; + +import static org.junit.jupiter.api.Assertions.assertFalse; + +import org.junit.jupiter.api.Test; + +public class ReflectionsUnitTest { + + @Test + public void givenTypeThenGetAllSubTypes() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getReflectionsSubTypes() + .isEmpty()); + } + + @Test + public void givenTypeAndUsingBuilderThenGetAllSubTypes() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getReflectionsSubTypesUsingBuilder() + .isEmpty()); + } + + @Test + public void givenAnnotationThenGetAllAnnotatedMethods() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getDateDeprecatedMethods() + .isEmpty()); + } + + @Test + public void givenAnnotationThenGetAllAnnotatedConstructors() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getDateDeprecatedConstructors() + .isEmpty()); + } + + @Test + public void givenParamTypeThenGetAllMethods() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getMethodsWithDateParam() + .isEmpty()); + } + + @Test + public void givenReturnTypeThenGetAllMethods() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getMethodsWithVoidReturn() + .isEmpty()); + } +} diff --git a/maven/.gitignore b/maven/.gitignore index f843ae9109..bae0b0d7ce 100644 --- a/maven/.gitignore +++ b/maven/.gitignore @@ -1 +1,2 @@ -/output-resources \ No newline at end of file +/output-resources +/.idea/ diff --git a/maven/custom-rule/pom.xml b/maven/custom-rule/pom.xml new file mode 100644 index 0000000000..f76e0db11e --- /dev/null +++ b/maven/custom-rule/pom.xml @@ -0,0 +1,69 @@ + + + + maven + com.baeldung + 0.0.1-SNAPSHOT + + 4.0.0 + custom-rule + + + 3.0.0-M2 + 2.0.9 + + + + + + + org.apache.maven.enforcer + enforcer-api + ${api.version} + + + org.apache.maven + maven-project + ${maven.version} + + + org.apache.maven + maven-core + ${maven.version} + + + org.apache.maven + maven-artifact + ${maven.version} + + + org.apache.maven + maven-plugin-api + ${maven.version} + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-9 + + + + + + + maven-verifier-plugin + ${maven.verifier.version} + + ../input-resources/verifications.xml + false + + + + + + + + + \ No newline at end of file diff --git a/maven/custom-rule/src/main/java/com/baeldung/enforcer/MyCustomRule.java b/maven/custom-rule/src/main/java/com/baeldung/enforcer/MyCustomRule.java new file mode 100644 index 0000000000..9b72f40bf1 --- /dev/null +++ b/maven/custom-rule/src/main/java/com/baeldung/enforcer/MyCustomRule.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 PloyRef + * Created by Seun Matt + * on 19 - 2 - 2019 + */ + +package com.baeldung.enforcer; + +import org.apache.maven.enforcer.rule.api.EnforcerRule; +import org.apache.maven.enforcer.rule.api.EnforcerRuleException; +import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; + +public class MyCustomRule implements EnforcerRule { + + public void execute(EnforcerRuleHelper enforcerRuleHelper) throws EnforcerRuleException { + + try { + + String groupId = (String) enforcerRuleHelper.evaluate("${project.groupId}"); + + if (groupId == null || !groupId.startsWith("org.baeldung")) { + throw new EnforcerRuleException("Project group id does not start with org.baeldung"); + } + + } + catch (ExpressionEvaluationException ex ) { + throw new EnforcerRuleException( "Unable to lookup an expression " + ex.getLocalizedMessage(), ex ); + } + } + + public boolean isCacheable() { + return false; + } + + public boolean isResultValid(EnforcerRule enforcerRule) { + return false; + } + + public String getCacheId() { + return null; + } +} diff --git a/maven/maven-enforcer/pom.xml b/maven/maven-enforcer/pom.xml new file mode 100644 index 0000000000..d54471e66c --- /dev/null +++ b/maven/maven-enforcer/pom.xml @@ -0,0 +1,74 @@ + + + + maven + com.baeldung + 0.0.1-SNAPSHOT + + 4.0.0 + maven-enforcer + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M2 + + + + + + + + + + enforce + + enforce + + + + + + 3.0 + Invalid Maven version. It should, at least, be 3.0 + + + 1.8 + + + ui + WARN + + + cook + WARN + + + local,base + Missing active profiles + WARN + + + + + + + + + + maven-verifier-plugin + ${maven.verifier.version} + + ../input-resources/verifications.xml + false + + + + + + + \ No newline at end of file diff --git a/maven/pom.xml b/maven/pom.xml index 01fd28db74..942bf683e2 100644 --- a/maven/pom.xml +++ b/maven/pom.xml @@ -4,8 +4,12 @@ com.baeldung maven 0.0.1-SNAPSHOT - maven - war + + custom-rule + maven-enforcer + + maven + pom diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml b/persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml index a181360e2b..882b88b535 100644 --- a/persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml +++ b/persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml @@ -11,10 +11,10 @@ Demo Spring Boot applications that starts H2 in memory database - org.springframework.boot - spring-boot-starter-parent - 2.0.4.RELEASE - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../../parent-boot-2 @@ -48,6 +48,7 @@ 1.8 com.baeldung.h2db.demo.server.SpringBootApp + 2.0.4.RELEASE diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java index 7d6b076517..fc6e72460a 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java @@ -67,10 +67,14 @@ public interface UserRepository extends JpaRepository , UserRepos @Query(value = "UPDATE Users u SET u.status = ? WHERE u.name = ?", nativeQuery = true) int updateUserSetStatusForNameNative(Integer status, String name); + @Query(value = "INSERT INTO Users (name, age, email, status) VALUES (:name, :age, :email, :status)", nativeQuery = true) + @Modifying + void insertUser(@Param("name") String name, @Param("age") Integer age, @Param("status") Integer status, @Param("email") String email); + @Modifying @Query(value = "UPDATE Users u SET status = ? WHERE u.name = ?", nativeQuery = true) int updateUserSetStatusForNameNativePostgres(Integer status, String name); @Query(value = "SELECT u FROM User u WHERE u.name IN :names") - List findUserByNameList(@Param("names") Collection names); + List findUserByNameList(@Param("names") Collection names); } diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryCommon.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryCommon.java index 55a453e48f..03cb20a858 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryCommon.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryCommon.java @@ -12,11 +12,7 @@ import org.springframework.data.jpa.domain.JpaSort; import org.springframework.data.mapping.PropertyReferenceException; import org.springframework.transaction.annotation.Transactional; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; @@ -29,10 +25,10 @@ class UserRepositoryCommon { final String USER_EMAIL4 = "email4@example.com"; final Integer INACTIVE_STATUS = 0; final Integer ACTIVE_STATUS = 1; - private final String USER_EMAIL5 = "email5@example.com"; - private final String USER_EMAIL6 = "email6@example.com"; - private final String USER_NAME_ADAM = "Adam"; - private final String USER_NAME_PETER = "Peter"; + final String USER_EMAIL5 = "email5@example.com"; + final String USER_EMAIL6 = "email6@example.com"; + final String USER_NAME_ADAM = "Adam"; + final String USER_NAME_PETER = "Peter"; @Autowired protected UserRepository userRepository; @@ -384,6 +380,22 @@ class UserRepositoryCommon { assertThat(usersWithNames.size()).isEqualTo(2); } + + + @Test + @Transactional + public void whenInsertedWithQuery_ThenUserIsPersisted() { + userRepository.insertUser(USER_NAME_ADAM, 1, ACTIVE_STATUS, USER_EMAIL); + userRepository.insertUser(USER_NAME_PETER, 1, ACTIVE_STATUS, USER_EMAIL2); + + User userAdam = userRepository.findUserByNameLike(USER_NAME_ADAM); + User userPeter = userRepository.findUserByNameLike(USER_NAME_PETER); + + assertThat(userAdam).isNotNull(); + assertThat(userAdam.getEmail()).isEqualTo(USER_EMAIL); + assertThat(userPeter).isNotNull(); + assertThat(userPeter.getEmail()).isEqualTo(USER_EMAIL2); + } @After public void cleanUp() { diff --git a/pom.xml b/pom.xml index b4bab0a389..4d4cd574d7 100644 --- a/pom.xml +++ b/pom.xml @@ -475,6 +475,7 @@ kotlin-libraries + libraries libraries-data libraries-apache-commons libraries-security diff --git a/spring-5-reactive-oauth/pom.xml b/spring-5-reactive-oauth/pom.xml index 86a5233ad4..ff076985e4 100644 --- a/spring-5-reactive-oauth/pom.xml +++ b/spring-5-reactive-oauth/pom.xml @@ -10,11 +10,11 @@ WebFluc and Spring Security OAuth - org.springframework.boot - spring-boot-starter-parent - 2.1.0.RELEASE - - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + @@ -70,6 +70,7 @@ UTF-8 UTF-8 1.8 + 2.1.0.RELEASE diff --git a/spring-5/pom.xml b/spring-5/pom.xml index 701aa3831d..6e4162fbcc 100644 --- a/spring-5/pom.xml +++ b/spring-5/pom.xml @@ -89,12 +89,6 @@ org.junit.jupiter junit-jupiter-api - - org.awaitility - awaitility - ${awaitility.version} - test - org.springframework.restdocs @@ -162,7 +156,6 @@ 4.1 ${project.build.directory}/generated-snippets 2.21.0 - 3.1.6 diff --git a/spring-boot-data/README.md b/spring-boot-data/README.md new file mode 100644 index 0000000000..21f7303c48 --- /dev/null +++ b/spring-boot-data/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Formatting JSON Dates in Spring ](https://www.baeldung.com/spring-boot-formatting-json-dates) \ No newline at end of file diff --git a/spring-boot-data/pom.xml b/spring-boot-data/pom.xml new file mode 100644 index 0000000000..9ef4cc69c8 --- /dev/null +++ b/spring-boot-data/pom.xml @@ -0,0 +1,122 @@ + + + 4.0.0 + spring-boot-data + war + spring-boot-data + Spring Boot Data Module + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + spring-boot + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-war-plugin + + + + pl.project13.maven + git-commit-id-plugin + ${git-commit-id-plugin.version} + + + get-the-git-infos + + revision + + initialize + + + validate-the-git-infos + + validateRevision + + package + + + + true + ${project.build.outputDirectory}/git.properties + + + + + + + + + autoconfiguration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*LiveTest.java + **/*IntegrationTest.java + **/*IntTest.java + + + **/AutoconfigurationTest.java + + + + + + + json + + + + + + + + + + com.baeldung.SpringBootDataApplication + 2.2.4 + + + \ No newline at end of file diff --git a/spring-boot-data/src/main/java/com/baeldung/SpringBootDataApplication.java b/spring-boot-data/src/main/java/com/baeldung/SpringBootDataApplication.java new file mode 100644 index 0000000000..3aa093bb41 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/SpringBootDataApplication.java @@ -0,0 +1,13 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBootDataApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBootDataApplication.class, args); + } + +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/Contact.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/Contact.java new file mode 100644 index 0000000000..f131d17196 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/Contact.java @@ -0,0 +1,70 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +public class Contact { + + private String name; + private String address; + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private LocalDate birthday; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private LocalDateTime lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public LocalDate getBirthday() { + return birthday; + } + + public void setBirthday(LocalDate birthday) { + this.birthday = birthday; + } + + public LocalDateTime getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(LocalDateTime lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public Contact() { + } + + public Contact(String name, String address, String phone, LocalDate birthday, LocalDateTime lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactApp.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactApp.java new file mode 100644 index 0000000000..79037e1038 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactApp.java @@ -0,0 +1,13 @@ +package com.baeldung.jsondateformat; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ContactApp { + + public static void main(String[] args) { + SpringApplication.run(ContactApp.class, args); + } + +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java new file mode 100644 index 0000000000..7a20ebfa51 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java @@ -0,0 +1,33 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import java.time.format.DateTimeFormatter; + +@Configuration +public class ContactAppConfig { + + private static final String dateFormat = "yyyy-MM-dd"; + + private static final String dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; + + @Bean + @ConditionalOnProperty(value = "spring.jackson.date-format", matchIfMissing = true, havingValue = "none") + public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { + return new Jackson2ObjectMapperBuilderCustomizer() { + @Override + public void customize(Jackson2ObjectMapperBuilder builder) { + builder.simpleDateFormat(dateTimeFormat); + builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat))); + builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat))); + } + }; + } + +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactController.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactController.java new file mode 100644 index 0000000000..8894d82fc7 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactController.java @@ -0,0 +1,77 @@ +package com.baeldung.jsondateformat; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@RestController +@RequestMapping(value = "/contacts") +public class ContactController { + + @GetMapping + public List getContacts() { + List contacts = new ArrayList<>(); + + Contact contact1 = new Contact("John Doe", "123 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + Contact contact2 = new Contact("John Doe 2", "124 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + Contact contact3 = new Contact("John Doe 3", "125 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + + @GetMapping("/javaUtilDate") + public List getContactsWithJavaUtilDate() { + List contacts = new ArrayList<>(); + + ContactWithJavaUtilDate contact1 = new ContactWithJavaUtilDate("John Doe", "123 Sesame Street", "123-456-789", new Date(), new Date()); + ContactWithJavaUtilDate contact2 = new ContactWithJavaUtilDate("John Doe 2", "124 Sesame Street", "123-456-789", new Date(), new Date()); + ContactWithJavaUtilDate contact3 = new ContactWithJavaUtilDate("John Doe 3", "125 Sesame Street", "123-456-789", new Date(), new Date()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + + @GetMapping("/plain") + public List getPlainContacts() { + List contacts = new ArrayList<>(); + + PlainContact contact1 = new PlainContact("John Doe", "123 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + PlainContact contact2 = new PlainContact("John Doe 2", "124 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + PlainContact contact3 = new PlainContact("John Doe 3", "125 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + + @GetMapping("/plainWithJavaUtilDate") + public List getPlainContactsWithJavaUtilDate() { + List contacts = new ArrayList<>(); + + PlainContactWithJavaUtilDate contact1 = new PlainContactWithJavaUtilDate("John Doe", "123 Sesame Street", "123-456-789", new Date(), new Date()); + PlainContactWithJavaUtilDate contact2 = new PlainContactWithJavaUtilDate("John Doe 2", "124 Sesame Street", "123-456-789", new Date(), new Date()); + PlainContactWithJavaUtilDate contact3 = new PlainContactWithJavaUtilDate("John Doe 3", "125 Sesame Street", "123-456-789", new Date(), new Date()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java new file mode 100644 index 0000000000..5a1c508098 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java @@ -0,0 +1,69 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.util.Date; + +public class ContactWithJavaUtilDate { + + private String name; + private String address; + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private Date birthday; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + public Date getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(Date lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public ContactWithJavaUtilDate() { + } + + public ContactWithJavaUtilDate(String name, String address, String phone, Date birthday, Date lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContact.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContact.java new file mode 100644 index 0000000000..7e9e53d205 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContact.java @@ -0,0 +1,66 @@ +package com.baeldung.jsondateformat; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +public class PlainContact { + + private String name; + private String address; + private String phone; + + private LocalDate birthday; + + private LocalDateTime lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public LocalDate getBirthday() { + return birthday; + } + + public void setBirthday(LocalDate birthday) { + this.birthday = birthday; + } + + public LocalDateTime getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(LocalDateTime lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public PlainContact() { + } + + public PlainContact(String name, String address, String phone, LocalDate birthday, LocalDateTime lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java new file mode 100644 index 0000000000..daefb15543 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java @@ -0,0 +1,69 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.util.Date; + +public class PlainContactWithJavaUtilDate { + + private String name; + private String address; + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private Date birthday; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + public Date getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(Date lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public PlainContactWithJavaUtilDate() { + } + + public PlainContactWithJavaUtilDate(String name, String address, String phone, Date birthday, Date lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot-data/src/main/resources/application.properties b/spring-boot-data/src/main/resources/application.properties new file mode 100644 index 0000000000..845b783634 --- /dev/null +++ b/spring-boot-data/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.jackson.date-format=yyyy-MM-dd HH:mm:ss +spring.jackson.time-zone=Europe/Zagreb \ No newline at end of file diff --git a/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java b/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java new file mode 100644 index 0000000000..f76440d1bc --- /dev/null +++ b/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java @@ -0,0 +1,100 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; +import java.text.ParseException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = RANDOM_PORT, classes = ContactApp.class) +@TestPropertySource(properties = { + "spring.jackson.date-format=yyyy-MM-dd HH:mm:ss" +}) +public class ContactAppIntegrationTest { + + private final ObjectMapper mapper = new ObjectMapper(); + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate restTemplate; + + @Test + public void givenJsonFormatAnnotationAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException, ParseException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test + public void givenJsonFormatAnnotationAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/javaUtilDate", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test + public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/plainWithJavaUtilDate", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test(expected = DateTimeParseException.class) + public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenNotApplyFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/plain", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + } + +} diff --git a/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java b/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java new file mode 100644 index 0000000000..c286012653 --- /dev/null +++ b/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java @@ -0,0 +1,67 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = RANDOM_PORT, classes = ContactApp.class) +public class ContactAppWithObjectMapperCustomizerIntegrationTest { + + private final ObjectMapper mapper = new ObjectMapper(); + + @Autowired + private TestRestTemplate restTemplate; + + @LocalServerPort + private int port; + + @Test + public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + this.port + "/contacts/plainWithJavaUtilDate", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test + public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + this.port + "/contacts/plain", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + +} diff --git a/spring-boot-data/src/test/resources/application.properties b/spring-boot-data/src/test/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index 3fbd21f24e..447dd07159 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -6,3 +6,5 @@ Module for the articles that are part of the Spring REST E-book: 4. [Build a REST API with Spring and Java Config](http://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration) 5. [HATEOAS for a Spring REST Service](http://www.baeldung.com/rest-api-discoverability-with-spring) 6. [REST API Discoverability and HATEOAS](http://www.baeldung.com/restful-web-service-discoverability) +7. [Versioning a REST API](http://www.baeldung.com/rest-versioning) +8. [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index 3c8c4d7486..decaccd148 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -25,16 +25,26 @@ com.fasterxml.jackson.dataformat jackson-dataformat-xml - + + + org.springframework + spring-oxm + + + com.thoughtworks.xstream + xstream + ${xstream.version} + + com.h2database h2 - + org.springframework.boot spring-boot-starter-data-jpa - - + + @@ -67,5 +77,6 @@ com.baeldung.SpringBootRestApplication 27.0.1-jre + 1.4.11.1 diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java index 9af3d07bed..f19d1c0e0b 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java @@ -8,6 +8,9 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import com.thoughtworks.xstream.annotations.XStreamAlias; + +@XStreamAlias("Foo") @Entity public class Foo implements Serializable { diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java index 80ee975e84..f581e4ec10 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java @@ -1,10 +1,49 @@ package com.baeldung.spring; +import java.util.List; + +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; +import org.springframework.oxm.xstream.XStreamMarshaller; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - @Configuration +// If we want to enable xml configurations for message-converter: +// @ImportResource("classpath:WEB-INF/api-servlet.xml") public class WebConfig implements WebMvcConfigurer { + // @Override + // public void configureMessageConverters(final List> messageConverters) { + // messageConverters.add(new MappingJackson2HttpMessageConverter()); + // messageConverters.add(createXmlHttpMessageConverter()); + // } + // + // private HttpMessageConverter createXmlHttpMessageConverter() { + // final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); + // + // final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); + // xstreamMarshaller.setAutodetectAnnotations(true); + // xmlConverter.setMarshaller(xstreamMarshaller); + // xmlConverter.setUnmarshaller(xstreamMarshaller); + // + // return xmlConverter; + // } + + // Another possibility is to create a bean which will be automatically added to the Spring Boot Autoconfigurations +// @Bean +// public HttpMessageConverter createXmlHttpMessageConverter() { +// final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); +// +// final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); +// xstreamMarshaller.setAutodetectAnnotations(true); +// xmlConverter.setMarshaller(xstreamMarshaller); +// xmlConverter.setUnmarshaller(xstreamMarshaller); +// +// return xmlConverter; +// } + } \ No newline at end of file diff --git a/spring-boot-rest/src/main/resources/WEB-INF/api-servlet.xml b/spring-boot-rest/src/main/resources/WEB-INF/api-servlet.xml new file mode 100644 index 0000000000..78e38e1448 --- /dev/null +++ b/spring-boot-rest/src/main/resources/WEB-INF/api-servlet.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json b/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json new file mode 100644 index 0000000000..5a6230bd22 --- /dev/null +++ b/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json @@ -0,0 +1,184 @@ +{ + "info": { + "_postman_id": "9989b5be-13ba-4d22-8e43-d05dbf628e58", + "name": "foo API test", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "add a foo", + "event": [ + { + "listen": "test", + "script": { + "id": "a01534dc-6fc7-4c54-ba1d-6bcf311e5836", + "exec": [ + "pm.test(\"success status\", () => pm.response.to.be.success );", + "", + "pm.test(\"name is correct\", () => ", + " pm.expect(pm.response.json().name).to.equal(\"Transformers\"));", + "", + "pm.test(\"id was assigned\", () => ", + " pm.expect(pm.response.json().id).to.be.not.null );", + "", + "pm.variables.set(\"id\", pm.response.json().id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Transformers\"\n}" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos" + ] + } + }, + "response": [] + }, + { + "name": "get a foo", + "event": [ + { + "listen": "test", + "script": { + "id": "03de440c-b483-4ab8-a11a-d0c99b349963", + "exec": [ + "pm.test(\"success status\", () => pm.response.to.be.success );", + "", + "pm.test(\"name is correct\", () => ", + " pm.expect(pm.response.json().name).to.equal(\"Transformers\"));", + "", + "pm.test(\"id is correct\", () => ", + " pm.expect(pm.response.json().id).to.equal(pm.variables.get(\"id\")) );" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "delete a foo", + "event": [ + { + "listen": "test", + "script": { + "id": "74c1bb0f-c06c-48b1-a545-459233541b14", + "exec": [ + "pm.test(\"success status\", () => pm.response.to.be.success );" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "verify delete", + "event": [ + { + "listen": "test", + "script": { + "id": "03de440c-b483-4ab8-a11a-d0c99b349963", + "exec": [ + "pm.test(\"status is 500\", () => pm.response.to.have.status(500) );", + "", + "pm.test(\"no value present\", () => ", + " pm.expect(pm.response.json().cause).to.equal(\"No value present\"));" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos", + "{{id}}" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerUnitTest.java b/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerIntegrationTest.java similarity index 98% rename from spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerUnitTest.java rename to spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerIntegrationTest.java index 0585c06a59..654e7925b9 100644 --- a/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerUnitTest.java +++ b/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerIntegrationTest.java @@ -13,7 +13,7 @@ import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = SpringBootSecurityTagLibsApplication.class) -public class HomeControllerUnitTest { +public class HomeControllerIntegrationTest { @Autowired private TestRestTemplate restTemplate; diff --git a/spring-boot/src/main/resources/application.properties b/spring-boot/src/main/resources/application.properties index 00c251d823..918fe5ea67 100644 --- a/spring-boot/src/main/resources/application.properties +++ b/spring-boot/src/main/resources/application.properties @@ -72,6 +72,3 @@ chaos.monkey.watcher.service=true chaos.monkey.watcher.repository=false #Component watcher active chaos.monkey.watcher.component=false - -spring.jackson.date-format=yyyy-MM-dd HH:mm:ss -spring.jackson.time-zone=Europe/Zagreb diff --git a/spring-cloud/spring-cloud-functions/pom.xml b/spring-cloud/spring-cloud-functions/pom.xml index 9396ad0a55..4d03e07e89 100644 --- a/spring-cloud/spring-cloud-functions/pom.xml +++ b/spring-cloud/spring-cloud-functions/pom.xml @@ -11,19 +11,12 @@ jar - org.springframework.boot - spring-boot-starter-parent - 2.0.4.RELEASE - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 - - UTF-8 - UTF-8 - 1.8 - 1.0.1.RELEASE - 2.0.2 - @@ -89,4 +82,13 @@ + + UTF-8 + UTF-8 + 1.8 + 1.0.1.RELEASE + 2.0.2 + 2.0.4.RELEASE + + diff --git a/spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/CloudFunctionApplicationTests.java b/spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/CloudFunctionApplicationUnitTest.java similarity index 96% rename from spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/CloudFunctionApplicationTests.java rename to spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/CloudFunctionApplicationUnitTest.java index 6039debe3f..e7b3fc8498 100644 --- a/spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/CloudFunctionApplicationTests.java +++ b/spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/CloudFunctionApplicationUnitTest.java @@ -12,7 +12,7 @@ import static org.assertj.core.api.Java6Assertions.assertThat; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class CloudFunctionApplicationTests { +public class CloudFunctionApplicationUnitTest { @LocalServerPort private int port; diff --git a/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml b/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml index 9254718c81..b87f807391 100644 --- a/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml @@ -7,10 +7,10 @@ 1.0-SNAPSHOT - org.springframework.boot - spring-boot-starter-parent - 1.5.17.RELEASE - + parent-boot-1 + com.baeldung + 0.0.1-SNAPSHOT + ../../../parent-boot-1 @@ -44,6 +44,7 @@ UTF-8 UTF-8 1.8 + 1.5.17.RELEASE \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml b/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml index e22bb0a9fe..42fa10934b 100644 --- a/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml @@ -7,10 +7,10 @@ 1.0-SNAPSHOT - org.springframework.boot - spring-boot-starter-parent - 1.5.17.RELEASE - + parent-boot-1 + com.baeldung + 0.0.1-SNAPSHOT + ../../../parent-boot-1 @@ -44,6 +44,7 @@ UTF-8 UTF-8 1.8 + 1.5.17.RELEASE \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zuul/pom.xml b/spring-cloud/spring-cloud-zuul/pom.xml index 97e67f16d8..08990357d6 100644 --- a/spring-cloud/spring-cloud-zuul/pom.xml +++ b/spring-cloud/spring-cloud-zuul/pom.xml @@ -10,11 +10,11 @@ Demo project for Spring Boot - org.springframework.boot - spring-boot-starter-parent - 2.0.6.RELEASE - - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + @@ -72,6 +72,7 @@ UTF-8 1.8 Finchley.SR1 + 2.0.6.RELEASE diff --git a/spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerTest.java b/spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerUnitTest.java similarity index 99% rename from spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerTest.java rename to spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerUnitTest.java index d51f881112..d23ec836f9 100644 --- a/spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerTest.java +++ b/spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerUnitTest.java @@ -26,7 +26,7 @@ import org.springframework.test.context.junit4.SpringRunner; @AutoConfigureTestDatabase @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class GreetingControllerTest { +public class GreetingControllerUnitTest { private static final String SIMPLE_GREETING = "/greeting/simple"; private static final String ADVANCED_GREETING = "/greeting/advanced"; diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java new file mode 100644 index 0000000000..b77598c113 --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java @@ -0,0 +1,31 @@ +package com.baeldung.spring.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.validation.annotation.Validated; +import javax.validation.constraints.*; + +@Controller +@RequestMapping("/public/api/1") +@Validated +public class RequestAndPathVariableValidationController { + + @GetMapping("/name-for-day") + public String getNameOfDayByNumberRequestParam(@RequestParam @Min(1) @Max(7) Integer dayOfWeek) { + return dayOfWeek + ""; + } + + @GetMapping("/name-for-day/{dayOfWeek}") + public String getNameOfDayByPathVariable(@PathVariable("dayOfWeek") @Min(1) @Max(7) Integer dayOfWeek) { + return dayOfWeek + ""; + } + + @GetMapping("/valid-name") + public void validStringRequestParam(@RequestParam @NotBlank @Size(max = 10) @Pattern(regexp = "^[A-Z][a-zA-Z0-9]+$") String name) { + + } + +} diff --git a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java new file mode 100644 index 0000000000..318a15d8f7 --- /dev/null +++ b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java @@ -0,0 +1,72 @@ +package com.baeldung.spring.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.spring.ClientWebConfig; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = ClientWebConfig.class) +@WebAppConfiguration +public class RequestAndPathVariableValidationControllerIntegrationTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext webApplicationContext; + + @Before + public void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); + } + + @Test + public void getNameOfDayByNumberRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(5))) + .andExpect(status().isOk()); + } + + @Test + public void getNameOfDayByNumberRequestParam_whenGetWithRequestParamOutOfRange_thenReturn400() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(15))) + .andExpect(status().isBadRequest()); + } + + @Test + public void getNameOfDayByPathVariable_whenGetWithProperRequestParam_thenReturn200() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day/{dayOfWeek}", Integer.toString(5))).andExpect(status().isOk()); + } + + @Test + public void getNameOfDayByPathVariable_whenGetWithRequestParamOutOfRange_thenReturn400() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day/{dayOfWeek}", Integer.toString(15))) + .andExpect(status().isBadRequest()); + } + + @Test + public void validStringRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception { + mockMvc.perform(get("/public/api/1/valid-name").param("name", "John")).andExpect(status().isOk()); + } + + @Test + public void validStringRequestParam_whenGetWithTooLongRequestParam_thenReturn400() throws Exception { + mockMvc.perform(get("/public/api/1/valid-name").param("name", "asdfghjklqw")) + .andExpect(status().isBadRequest()); + } + + @Test + public void validStringRequestParam_whenGetWithLowerCaseRequestParam_thenReturn400() throws Exception { + mockMvc.perform(get("/public/api/1/valid-name").param("name", "john")).andExpect(status().isBadRequest()); + } +} diff --git a/spring-rest/README.md b/spring-rest/README.md index 4921ab012c..9a2c1fd96c 100644 --- a/spring-rest/README.md +++ b/spring-rest/README.md @@ -5,7 +5,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [Spring @RequestMapping](http://www.baeldung.com/spring-requestmapping) -- [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) - [Returning Custom Status Codes from Spring Controllers](http://www.baeldung.com/spring-mvc-controller-custom-http-status-code) - [A Guide to OkHttp](http://www.baeldung.com/guide-to-okhttp) - [Binary Data Formats in a Spring REST API](http://www.baeldung.com/spring-rest-api-with-binary-data-formats) diff --git a/spring-rest/pom.xml b/spring-rest/pom.xml index 5c88697cef..36934af101 100644 --- a/spring-rest/pom.xml +++ b/spring-rest/pom.xml @@ -52,10 +52,6 @@ org.springframework spring-webmvc - - org.springframework - spring-oxm - commons-fileupload commons-fileupload @@ -86,12 +82,6 @@ jackson-dataformat-xml - - com.thoughtworks.xstream - xstream - ${xstream.version} - - com.google.guava @@ -281,7 +271,6 @@ 1.4 3.1.0 3.5 - 1.4.9 20.0 diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java b/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java index d5209a520b..dc4fb9c695 100644 --- a/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java +++ b/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java @@ -8,8 +8,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; -import org.springframework.oxm.xstream.XStreamMarshaller; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -33,22 +31,12 @@ public class WebConfig implements WebMvcConfigurer { .dateFormat(new SimpleDateFormat("dd-MM-yyyy hh:mm")); messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build())); // messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build())); - - // messageConverters.add(createXmlHttpMessageConverter()); + // messageConverters.add(new MappingJackson2HttpMessageConverter()); // messageConverters.add(new ProtobufHttpMessageConverter()); } - private HttpMessageConverter createXmlHttpMessageConverter() { - final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); - - final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); - xmlConverter.setMarshaller(xstreamMarshaller); - xmlConverter.setUnmarshaller(xstreamMarshaller); - - return xmlConverter; - } */ } diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java b/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java index 186df8e678..de1d76ed92 100644 --- a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java +++ b/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java @@ -1,8 +1,5 @@ package com.baeldung.sampleapp.web.dto; -import com.thoughtworks.xstream.annotations.XStreamAlias; - -@XStreamAlias("Foo") public class Foo { private long id; private String name; diff --git a/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml b/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml index ddb9c91792..3d83ebf6c9 100644 --- a/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml +++ b/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml @@ -10,21 +10,11 @@ - - - diff --git a/spring-security-angular/README.md b/spring-security-angular/README.md index 80312c4bab..49cd8dd62d 100644 --- a/spring-security-angular/README.md +++ b/spring-security-angular/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Spring Security Login Page with Angular](https://www.baeldung.com/spring-security-login-angular) +- [Fixing 401s with CORS Preflights and Spring Security](https://www.baeldung.com/spring-security-cors-preflight) diff --git a/testing-modules/rest-testing/README.md b/testing-modules/rest-testing/README.md index ab038807bc..25e036ba5d 100644 --- a/testing-modules/rest-testing/README.md +++ b/testing-modules/rest-testing/README.md @@ -8,6 +8,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [Test a REST API with Java](http://www.baeldung.com/integration-testing-a-rest-api) - [Introduction to WireMock](http://www.baeldung.com/introduction-to-wiremock) +- [Using WireMock Scenarios](http://www.baeldung.com/using-wiremock-scenarios) - [REST API Testing with Cucumber](http://www.baeldung.com/cucumber-rest-api-testing) - [Testing a REST API with JBehave](http://www.baeldung.com/jbehave-rest-testing) - [REST API Testing with Karate](http://www.baeldung.com/karate-rest-api-testing) diff --git a/testing-modules/rest-testing/pom.xml b/testing-modules/rest-testing/pom.xml index 2b1f146f0f..c3a9477a47 100644 --- a/testing-modules/rest-testing/pom.xml +++ b/testing-modules/rest-testing/pom.xml @@ -159,7 +159,7 @@ 2.9.0 1.2.5 - 2.4.1 + 2.21.0 0.6.1 4.4.5 diff --git a/testing-modules/rest-testing/src/test/java/com/baeldung/rest/wiremock/scenario/WireMockScenarioExampleIntegrationTest.java b/testing-modules/rest-testing/src/test/java/com/baeldung/rest/wiremock/scenario/WireMockScenarioExampleIntegrationTest.java new file mode 100644 index 0000000000..946d3d717f --- /dev/null +++ b/testing-modules/rest-testing/src/test/java/com/baeldung/rest/wiremock/scenario/WireMockScenarioExampleIntegrationTest.java @@ -0,0 +1,75 @@ +package com.baeldung.rest.wiremock.scenario; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.junit.Rule; +import org.junit.Test; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.github.tomakehurst.wiremock.stubbing.Scenario; + +public class WireMockScenarioExampleIntegrationTest { + + private static final String THIRD_STATE = "third"; + private static final String SECOND_STATE = "second"; + private static final String TIP_01 = "finally block is not called when System.exit() is called in the try block"; + private static final String TIP_02 = "keep your code clean"; + private static final String TIP_03 = "use composition rather than inheritance"; + private static final String TEXT_PLAIN = "text/plain"; + + static int port = 9999; + + @Rule + public WireMockRule wireMockRule = new WireMockRule(port); + + @Test + public void changeStateOnEachCallTest() throws IOException { + createWireMockStub(Scenario.STARTED, SECOND_STATE, TIP_01); + createWireMockStub(SECOND_STATE, THIRD_STATE, TIP_02); + createWireMockStub(THIRD_STATE, Scenario.STARTED, TIP_03); + + assertEquals(TIP_01, nextTip()); + assertEquals(TIP_02, nextTip()); + assertEquals(TIP_03, nextTip()); + assertEquals(TIP_01, nextTip()); + } + + private void createWireMockStub(String currentState, String nextState, String responseBody) { + stubFor(get(urlEqualTo("/java-tip")) + .inScenario("java tips") + .whenScenarioStateIs(currentState) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", TEXT_PLAIN) + .withBody(responseBody)) + .willSetStateTo(nextState) + ); + } + + private String nextTip() throws ClientProtocolException, IOException { + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpGet request = new HttpGet(String.format("http://localhost:%s/java-tip", port)); + HttpResponse httpResponse = httpClient.execute(request); + return firstLineOfResponse(httpResponse); + } + + private static String firstLineOfResponse(HttpResponse httpResponse) throws IOException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()))) { + return reader.readLine(); + } + } + +} diff --git a/testing-modules/spring-testing/pom.xml b/testing-modules/spring-testing/pom.xml index a137bc8d33..630aed0c81 100644 --- a/testing-modules/spring-testing/pom.xml +++ b/testing-modules/spring-testing/pom.xml @@ -54,6 +54,18 @@ spring-data-jpa LATEST + + org.junit.jupiter + junit-jupiter + ${junit.jupiter.version} + test + + + org.awaitility + awaitility + ${awaitility.version} + test + @@ -70,6 +82,8 @@ 2.0.0.0 + 3.1.6 + 5.4.0 \ No newline at end of file diff --git a/spring-5/src/main/java/com/baeldung/config/ScheduledConfig.java b/testing-modules/spring-testing/src/main/java/com/baeldung/config/ScheduledConfig.java similarity index 100% rename from spring-5/src/main/java/com/baeldung/config/ScheduledConfig.java rename to testing-modules/spring-testing/src/main/java/com/baeldung/config/ScheduledConfig.java diff --git a/spring-5/src/main/java/com/baeldung/scheduled/Counter.java b/testing-modules/spring-testing/src/main/java/com/baeldung/scheduled/Counter.java similarity index 100% rename from spring-5/src/main/java/com/baeldung/scheduled/Counter.java rename to testing-modules/spring-testing/src/main/java/com/baeldung/scheduled/Counter.java diff --git a/spring-5/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java similarity index 100% rename from spring-5/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java rename to testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java diff --git a/spring-5/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java similarity index 100% rename from spring-5/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java rename to testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java