diff --git a/algorithms-miscellaneous-1/README.md b/algorithms-miscellaneous-1/README.md index 6f18396005..7ed805f7c4 100644 --- a/algorithms-miscellaneous-1/README.md +++ b/algorithms-miscellaneous-1/README.md @@ -15,3 +15,5 @@ - [Find Substrings That Are Palindromes in Java](https://www.baeldung.com/java-palindrome-substrings) - [Find the Longest Substring without Repeating Characters](https://www.baeldung.com/java-longest-substring-without-repeated-characters) - [Java Two Pointer Technique](https://www.baeldung.com/java-two-pointer-technique) +- [Permutations of an Array in Java](https://www.baeldung.com/java-array-permutations) +- [Implementing Simple State Machines with Java Enums](https://www.baeldung.com/java-enum-simple-state-machine) diff --git a/apache-spark/README.md b/apache-spark/README.md index fb8059eb27..a4dce212b4 100644 --- a/apache-spark/README.md +++ b/apache-spark/README.md @@ -1,3 +1,4 @@ ### Relevant articles - [Introduction to Apache Spark](http://www.baeldung.com/apache-spark) +- [Building a Data Pipeline with Kafka, Spark Streaming and Cassandra](https://www.baeldung.com/kafka-spark-data-pipeline) diff --git a/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy b/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy new file mode 100644 index 0000000000..b3a0852a0b --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy @@ -0,0 +1,43 @@ +package com.baeldung.strings; + +class Concatenate { + String first = 'Hello' + String last = 'Groovy' + + String doSimpleConcat() { + return 'My name is ' + first + ' ' + last + } + + String doConcatUsingGString() { + return "My name is $first $last" + } + + String doConcatUsingGStringClosures() { + return "My name is ${-> first} ${-> last}" + } + + String doConcatUsingStringConcatMethod() { + return 'My name is '.concat(first).concat(' ').concat(last) + } + + String doConcatUsingLeftShiftOperator() { + return 'My name is ' << first << ' ' << last + } + + String doConcatUsingArrayJoinMethod() { + return ['My name is', first, last].join(' ') + } + + String doConcatUsingArrayInjectMethod() { + return [first,' ', last] + .inject(new StringBuffer('My name is '), { initial, name -> initial.append(name); return initial }).toString() + } + + String doConcatUsingStringBuilder() { + return new StringBuilder().append('My name is ').append(first).append(' ').append(last) + } + + String doConcatUsingStringBuffer() { + return new StringBuffer().append('My name is ').append(first).append(' ').append(last) + } +} \ No newline at end of file diff --git a/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy b/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy new file mode 100644 index 0000000000..3ef4a5d460 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy @@ -0,0 +1,101 @@ +import com.baeldung.strings.Concatenate; + +class ConcatenateTest extends GroovyTestCase { + + void testSimpleConcat() { + def name = new Concatenate() + name.first = 'Joe'; + name.last = 'Smith'; + def expected = 'My name is Joe Smith' + assertToString(name.doSimpleConcat(), expected) + } + + void testConcatUsingGString() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingGString(), expected) + } + + void testConcatUsingGStringClosures() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingGStringClosures(), expected) + } + + void testConcatUsingStringConcatMethod() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingStringConcatMethod(), expected) + } + + void testConcatUsingLeftShiftOperator() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingLeftShiftOperator(), expected) + } + + void testConcatUsingArrayJoinMethod() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingArrayJoinMethod(), expected) + } + + void testConcatUsingArrayInjectMethod() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingArrayInjectMethod(), expected) + } + + void testConcatUsingStringBuilder() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingStringBuilder(), expected) + } + + void testConcatUsingStringBuffer() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingStringBuffer(), expected) + } + + void testConcatMultilineUsingStringConcatMethod() { + def name = new Concatenate() + name.first = '''Joe + Smith + '''; + name.last = 'Junior'; + def expected = '''My name is Joe + Smith + Junior'''; + assertToString(name.doConcatUsingStringConcatMethod(), expected) + } + + void testGStringvsClosure(){ + def first = "Joe"; + def last = "Smith"; + def eagerGString = "My name is $first $last" + def lazyGString = "My name is ${-> first} ${-> last}" + + assert eagerGString == "My name is Joe Smith" + assert lazyGString == "My name is Joe Smith" + first = "David"; + assert eagerGString == "My name is Joe Smith" + assert lazyGString == "My name is David Smith" + } +} diff --git a/core-java-11/README.md b/core-java-11/README.md index c8039f4bc5..3c8b94fa28 100644 --- a/core-java-11/README.md +++ b/core-java-11/README.md @@ -3,3 +3,4 @@ - [Java 11 Single File Source Code](https://www.baeldung.com/java-single-file-source-code) - [Java 11 Local Variable Syntax for Lambda Parameters](https://www.baeldung.com/java-var-lambda-params) - [Java 11 String API Additions](https://www.baeldung.com/java-11-string-api) +- [Java 11 Nest Based Access Control](https://www.baeldung.com/java-nest-based-access-control) diff --git a/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java b/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java index bad1c32e4a..9ace27e38f 100644 --- a/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java +++ b/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java @@ -39,6 +39,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; public class Java8CollectorsUnitTest { private final List givenList = Arrays.asList("a", "bb", "ccc", "dd"); + private final List listWithDuplicates = Arrays.asList("a", "bb", "c", "d", "bb"); @Test public void whenCollectingToList_shouldCollectToList() throws Exception { @@ -48,12 +49,19 @@ public class Java8CollectorsUnitTest { } @Test - public void whenCollectingToList_shouldCollectToSet() throws Exception { + public void whenCollectingToSet_shouldCollectToSet() throws Exception { final Set result = givenList.stream().collect(toSet()); assertThat(result).containsAll(givenList); } + @Test + public void givenContainsDuplicateElements_whenCollectingToSet_shouldAddDuplicateElementsOnlyOnce() throws Exception { + final Set result = listWithDuplicates.stream().collect(toSet()); + + assertThat(result).hasSize(4); + } + @Test public void whenCollectingToCollection_shouldCollectToCollection() throws Exception { final List result = givenList.stream().collect(toCollection(LinkedList::new)); @@ -83,6 +91,13 @@ public class Java8CollectorsUnitTest { assertThat(result).containsEntry("a", 1).containsEntry("bb", 2).containsEntry("ccc", 3).containsEntry("dd", 2); } + @Test + public void givenContainsDuplicateElements_whenCollectingToMap_shouldThrowException() throws Exception { + assertThatThrownBy(() -> { + listWithDuplicates.stream().collect(toMap(Function.identity(), String::length)); + }).isInstanceOf(IllegalStateException.class); + } + @Test public void whenCollectingAndThen_shouldCollect() throws Exception { final List result = givenList.stream().collect(collectingAndThen(toList(), ImmutableList::copyOf)); diff --git a/core-java-9/README.md b/core-java-9/README.md index c96267dc95..d9586ba684 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -26,3 +26,4 @@ - [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap) - [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api) - [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api) +- [Immutable Set in Java](https://www.baeldung.com/java-immutable-set) diff --git a/core-java-arrays/README.md b/core-java-arrays/README.md index 400dd7793c..ed8221ebe4 100644 --- a/core-java-arrays/README.md +++ b/core-java-arrays/README.md @@ -14,3 +14,4 @@ - [Array Operations in Java](http://www.baeldung.com/java-common-array-operations) - [Intersection Between two Integer Arrays](https://www.baeldung.com/java-array-intersection) - [Sorting Arrays in Java](https://www.baeldung.com/java-sorting-arrays) +- [Convert a Float to a Byte Array in Java](https://www.baeldung.com/java-convert-float-to-byte-array) diff --git a/core-java-collections-list/pom.xml b/core-java-collections-list/pom.xml index ee99e470d0..a7e711088a 100644 --- a/core-java-collections-list/pom.xml +++ b/core-java-collections-list/pom.xml @@ -36,6 +36,22 @@ ${lombok.version} provided + + + net.sf.trove4j + trove4j + 3.0.2 + + + it.unimi.dsi + fastutil + 8.1.0 + + + colt + colt + 1.2.0 + diff --git a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java new file mode 100644 index 0000000000..01372763e9 --- /dev/null +++ b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java @@ -0,0 +1,52 @@ +package com.baeldung.list.primitive; + +import com.google.common.primitives.ImmutableIntArray; +import com.google.common.primitives.Ints; +import gnu.trove.list.array.TIntArrayList; +import it.unimi.dsi.fastutil.ints.IntArrayList; + +import java.util.Arrays; +import java.util.List; +import java.util.OptionalDouble; +import java.util.function.IntPredicate; +import java.util.stream.IntStream; + +public class PrimitiveCollections { + + public static void main(String[] args) { + + int[] primitives = new int[] {5, 10, 0, 2, -8}; + + guavaPrimitives(primitives); + + intStream(primitives); + + TIntArrayList tList = new TIntArrayList(primitives); + + cern.colt.list.IntArrayList coltList = new cern.colt.list.IntArrayList(primitives); + + IntArrayList fastUtilList = new IntArrayList(primitives); + + System.out.println(tList); + + System.out.println(coltList); + + System.out.println(fastUtilList); + } + + private static void intStream(int[] primitives) { + + IntStream stream = IntStream.of(5, 10, 0, 2, -8); + + IntStream newStream = IntStream.of(primitives); + + OptionalDouble average = stream.filter(i -> i > 0).average(); + } + + + private static void guavaPrimitives(int[] primitives) { + + ImmutableIntArray immutableIntArray = ImmutableIntArray.builder().addAll(primitives).build(); + System.out.println(immutableIntArray); + } +} diff --git a/core-java-collections/README.md b/core-java-collections/README.md index be83621429..710be31a08 100644 --- a/core-java-collections/README.md +++ b/core-java-collections/README.md @@ -31,3 +31,4 @@ - [A Guide to EnumMap](https://www.baeldung.com/java-enum-map) - [A Guide to Iterator in Java](http://www.baeldung.com/java-iterator) - [Differences Between HashMap and Hashtable](https://www.baeldung.com/hashmap-hashtable-differences) +- [Java ArrayList vs Vector](https://www.baeldung.com/java-arraylist-vs-vector) diff --git a/core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java b/core-java-collections/src/test/java/com/baeldung/queueinterface/PriorityQueueUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java rename to core-java-collections/src/test/java/com/baeldung/queueinterface/PriorityQueueUnitTest.java diff --git a/core-java-io/README.md b/core-java-io/README.md index 2ad980ca6a..9a25009849 100644 --- a/core-java-io/README.md +++ b/core-java-io/README.md @@ -36,4 +36,7 @@ - [Reading a CSV File into an Array](https://www.baeldung.com/java-csv-file-array) - [Guide to BufferedReader](https://www.baeldung.com/java-buffered-reader) - [How to Get the File Extension of a File in Java](http://www.baeldung.com/java-file-extension) -- [Getting a File’s Mime Type in Java](http://www.baeldung.com/java-file-mime-type) \ No newline at end of file +- [Getting a File’s Mime Type in Java](http://www.baeldung.com/java-file-mime-type) +- [Create a Directory in Java](https://www.baeldung.com/java-create-directory) +- [How to Write to a CSV File in Java](https://www.baeldung.com/java-csv) +- [List Files in a Directory in Java](https://www.baeldung.com/java-list-directory-files) diff --git a/core-java-lang-syntax/README.md b/core-java-lang-syntax/README.md index a7c1b7cc4a..99c8613929 100644 --- a/core-java-lang-syntax/README.md +++ b/core-java-lang-syntax/README.md @@ -16,4 +16,5 @@ - [Quick Guide to java.lang.System](http://www.baeldung.com/java-lang-system) - [Java Switch Statement](https://www.baeldung.com/java-switch) - [The Modulo Operator in Java](https://www.baeldung.com/modulo-java) -- [Ternary Operator In Java](https://www.baeldung.com/java-ternary-operator) \ No newline at end of file +- [Ternary Operator In Java](https://www.baeldung.com/java-ternary-operator) +- [Java instanceof Operator](https://www.baeldung.com/java-instanceof) diff --git a/core-java-lang/README.md b/core-java-lang/README.md index 7af962558d..c1c22caf6c 100644 --- a/core-java-lang/README.md +++ b/core-java-lang/README.md @@ -34,4 +34,10 @@ - [“Sneaky Throws” in Java](http://www.baeldung.com/java-sneaky-throws) - [Retrieving a Class Name in Java](https://www.baeldung.com/java-class-name) - [Java Compound Operators](https://www.baeldung.com/java-compound-operators) -- [Guide to Java Packages](https://www.baeldung.com/java-packages) \ No newline at end of file +- [Guide to Java Packages](https://www.baeldung.com/java-packages) +- [The Java Native Keyword and Methods](https://www.baeldung.com/java-native) +- [If-Else Statement in Java](https://www.baeldung.com/java-if-else) +- [Control Structures in Java](https://www.baeldung.com/java-control-structures) +- [Java Interfaces](https://www.baeldung.com/java-interfaces) +- [Attaching Values to Java Enum](https://www.baeldung.com/java-enum-values) +- [Variable Scope in Java](https://www.baeldung.com/java-variable-scope) diff --git a/core-java-lang/src/main/java/com/baeldung/scope/BracketScopeExample.java b/core-java-lang/src/main/java/com/baeldung/scope/BracketScopeExample.java index 37ae211dcb..8deec35c16 100644 --- a/core-java-lang/src/main/java/com/baeldung/scope/BracketScopeExample.java +++ b/core-java-lang/src/main/java/com/baeldung/scope/BracketScopeExample.java @@ -1,4 +1,4 @@ -package org.baeldung.variable.scope.examples; +package com.baeldung.scope; public class BracketScopeExample { diff --git a/core-java-lang/src/main/java/com/baeldung/scope/ClassScopeExample.java b/core-java-lang/src/main/java/com/baeldung/scope/ClassScopeExample.java index 241c6b466e..c81fcc9550 100644 --- a/core-java-lang/src/main/java/com/baeldung/scope/ClassScopeExample.java +++ b/core-java-lang/src/main/java/com/baeldung/scope/ClassScopeExample.java @@ -1,4 +1,4 @@ -package org.baeldung.variable.scope.examples; +package com.baeldung.scope; public class ClassScopeExample { diff --git a/core-java-lang/src/main/java/com/baeldung/scope/LoopScopeExample.java b/core-java-lang/src/main/java/com/baeldung/scope/LoopScopeExample.java index 7bf92a6d26..be41252623 100644 --- a/core-java-lang/src/main/java/com/baeldung/scope/LoopScopeExample.java +++ b/core-java-lang/src/main/java/com/baeldung/scope/LoopScopeExample.java @@ -1,4 +1,4 @@ -package org.baeldung.variable.scope.examples; +package com.baeldung.scope; import java.util.Arrays; import java.util.List; diff --git a/core-java-lang/src/main/java/com/baeldung/scope/MethodScopeExample.java b/core-java-lang/src/main/java/com/baeldung/scope/MethodScopeExample.java index e62c6a2a1c..63a6a25271 100644 --- a/core-java-lang/src/main/java/com/baeldung/scope/MethodScopeExample.java +++ b/core-java-lang/src/main/java/com/baeldung/scope/MethodScopeExample.java @@ -1,4 +1,4 @@ -package org.baeldung.variable.scope.examples; +package com.baeldung.scope; public class MethodScopeExample { diff --git a/core-java-lang/src/main/java/com/baeldung/scope/NestedScopesExample.java b/core-java-lang/src/main/java/com/baeldung/scope/NestedScopesExample.java index fcd23e5ae0..c3c5bec221 100644 --- a/core-java-lang/src/main/java/com/baeldung/scope/NestedScopesExample.java +++ b/core-java-lang/src/main/java/com/baeldung/scope/NestedScopesExample.java @@ -1,4 +1,4 @@ -package org.baeldung.variable.scope.examples; +package com.baeldung.scope; public class NestedScopesExample { diff --git a/core-java-lang/src/test/java/com/baeldung/java/enumiteration/EnumIterationExamples.java b/core-java-lang/src/test/java/com/baeldung/java/enumiteration/EnumIterationExamples.java index 2d874fa650..110943e39f 100644 --- a/core-java-lang/src/test/java/com/baeldung/java/enumiteration/EnumIterationExamples.java +++ b/core-java-lang/src/test/java/com/baeldung/java/enumiteration/EnumIterationExamples.java @@ -1,18 +1,43 @@ package com.baeldung.java.enumiteration; +import java.util.ArrayList; +import java.util.Arrays; import java.util.EnumSet; +import java.util.List; + public class EnumIterationExamples { public static void main(String[] args) { - System.out.println("Enum iteration using forEach:"); + System.out.println("Enum iteration using EnumSet:"); EnumSet.allOf(DaysOfWeekEnum.class).forEach(day -> System.out.println(day)); System.out.println("Enum iteration using Stream:"); DaysOfWeekEnum.stream().filter(d -> d.getTypeOfDay().equals("off")).forEach(System.out::println); - System.out.println("Enum iteration using for loop:"); + System.out.println("Enum iteration using a for loop:"); for (DaysOfWeekEnum day : DaysOfWeekEnum.values()) { System.out.println(day); } + + System.out.println("Enum iteration using Arrays.asList():"); + Arrays.asList(DaysOfWeekEnum.values()).forEach(day -> System.out.println(day)); + + System.out.println("Add Enum values to ArrayList:"); + List days = new ArrayList<>(); + days.add(DaysOfWeekEnum.FRIDAY); + days.add(DaysOfWeekEnum.SATURDAY); + days.add(DaysOfWeekEnum.SUNDAY); + for (DaysOfWeekEnum day : days) { + System.out.println(day); + } + System.out.println("Remove SATURDAY from the list:"); + days.remove(DaysOfWeekEnum.SATURDAY); + if (!days.contains(DaysOfWeekEnum.SATURDAY)) { + System.out.println("Saturday is no longer in the list"); + } + for (DaysOfWeekEnum day : days) { + System.out.println(day); + } + } } diff --git a/core-java-perf/README.md b/core-java-perf/README.md index 252ee4cc45..1b3b590bf8 100644 --- a/core-java-perf/README.md +++ b/core-java-perf/README.md @@ -5,4 +5,5 @@ - [Different Ways to Capture Java Heap Dumps](https://www.baeldung.com/java-heap-dump-capture) - [Understanding Memory Leaks in Java](https://www.baeldung.com/java-memory-leaks) - [OutOfMemoryError: GC Overhead Limit Exceeded](http://www.baeldung.com/java-gc-overhead-limit-exceeded) -- [Basic Introduction to JMX](http://www.baeldung.com/java-management-extensions) \ No newline at end of file +- [Basic Introduction to JMX](http://www.baeldung.com/java-management-extensions) +- [Monitoring Java Applications with Flight Recorder](https://www.baeldung.com/java-flight-recorder-monitoring) diff --git a/core-java-security/README.md b/core-java-security/README.md index 415171094b..d3343f79ca 100644 --- a/core-java-security/README.md +++ b/core-java-security/README.md @@ -8,4 +8,5 @@ - [Encrypting and Decrypting Files in Java](http://www.baeldung.com/java-cipher-input-output-stream) - [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing) - [SSL Handshake Failures](https://www.baeldung.com/java-ssl-handshake-failures) -- [SHA-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java) \ No newline at end of file +- [SHA-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java) +- [Enabling TLS v1.2 in Java 7](https://www.baeldung.com/java-7-tls-v12) diff --git a/core-java-security/pom.xml b/core-java-security/pom.xml index cf91121465..7c4ab9763f 100644 --- a/core-java-security/pom.xml +++ b/core-java-security/pom.xml @@ -44,8 +44,8 @@ 3.8.1 - 1.55 - 1.10 + 1.60 + 1.11 3.10.0 diff --git a/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java b/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java new file mode 100644 index 0000000000..94dd22ff4b --- /dev/null +++ b/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java @@ -0,0 +1,9 @@ +package com.baeldung.hashing; + +public class DigestAlgorithms { + + public static final String SHA3_256 = "SHA3-256"; + public static final String SHA_256 = "SHA-256"; + public static final String KECCAK_256 = "Keccak-256"; + +} diff --git a/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java b/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java new file mode 100644 index 0000000000..19fc4cf059 --- /dev/null +++ b/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java @@ -0,0 +1,30 @@ +package com.baeldung.hashing; + +import org.bouncycastle.jcajce.provider.digest.Keccak; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.encoders.Hex; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Security; + +import static com.baeldung.hashing.DigestAlgorithms.KECCAK_256; +import static com.baeldung.hashing.SHACommonUtils.bytesToHex; + +public class Keccak256Hashing { + + public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException { + Security.addProvider(new BouncyCastleProvider()); + final MessageDigest digest = MessageDigest.getInstance(KECCAK_256); + final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(encodedhash); + } + + public static String hashWithBouncyCastle(final String originalString) { + Keccak.Digest256 digest256 = new Keccak.Digest256(); + byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return new String(Hex.encode(hashbytes)); + } + +} diff --git a/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java b/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java index 4fa164cadc..ec008cebab 100644 --- a/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java +++ b/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java @@ -8,15 +8,18 @@ import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import static com.baeldung.hashing.DigestAlgorithms.SHA_256; +import static com.baeldung.hashing.SHACommonUtils.bytesToHex; + public class SHA256Hashing { public static String HashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException { - final MessageDigest digest = MessageDigest.getInstance("SHA-256"); + final MessageDigest digest = MessageDigest.getInstance(SHA_256); final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); return bytesToHex(encodedhash); } - public static String HashWithGuava(final String originalString) { + public static String hashWithGuava(final String originalString) { final String sha256hex = Hashing.sha256().hashString(originalString, StandardCharsets.UTF_8).toString(); return sha256hex; } @@ -27,20 +30,10 @@ public class SHA256Hashing { } public static String HashWithBouncyCastle(final String originalString) throws NoSuchAlgorithmException { - final MessageDigest digest = MessageDigest.getInstance("SHA-256"); + final MessageDigest digest = MessageDigest.getInstance(SHA_256); final byte[] hash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); final String sha256hex = new String(Hex.encode(hash)); return sha256hex; } - private static String bytesToHex(byte[] hash) { - StringBuffer hexString = new StringBuffer(); - for (int i = 0; i < hash.length; i++) { - String hex = Integer.toHexString(0xff & hash[i]); - if (hex.length() == 1) - hexString.append('0'); - hexString.append(hex); - } - return hexString.toString(); - } } diff --git a/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java b/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java new file mode 100644 index 0000000000..eb363205b1 --- /dev/null +++ b/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java @@ -0,0 +1,45 @@ +package com.baeldung.hashing; + +import com.google.common.hash.Hashing; +import org.apache.commons.codec.digest.DigestUtils; +import org.bouncycastle.crypto.digests.SHA3Digest; +import org.bouncycastle.jcajce.provider.digest.SHA3; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.encoders.Hex; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Security; + +import static com.baeldung.hashing.DigestAlgorithms.SHA3_256; +import static com.baeldung.hashing.SHACommonUtils.bytesToHex; + +public class SHA3Hashing { + + /* works with JDK9+ only */ + public static String hashWithJavaMessageDigestJDK9(final String originalString) throws NoSuchAlgorithmException { + final MessageDigest digest = MessageDigest.getInstance(SHA3_256); + final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(hashbytes); + } + + public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException { + Security.addProvider(new BouncyCastleProvider()); + final MessageDigest digest = MessageDigest.getInstance(SHA3_256); + final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(hashbytes); + } + + /* works with JDK9+ only */ + public static String hashWithApacheCommonsJDK9(final String originalString) { + return new DigestUtils(SHA3_256).digestAsHex(originalString); + } + + public static String hashWithBouncyCastle(final String originalString) { + SHA3.Digest256 digest256 = new SHA3.Digest256(); + byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return new String(Hex.encode(hashbytes)); + } + +} diff --git a/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java b/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java new file mode 100644 index 0000000000..0f28408083 --- /dev/null +++ b/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java @@ -0,0 +1,16 @@ +package com.baeldung.hashing; + +class SHACommonUtils { + + public static String bytesToHex(byte[] hash) { + StringBuffer hexString = new StringBuffer(); + for (byte h : hash) { + String hex = Integer.toHexString(0xff & h); + if (hex.length() == 1) + hexString.append('0'); + hexString.append(hex); + } + return hexString.toString(); + } + +} diff --git a/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java b/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java new file mode 100644 index 0000000000..9ed35c8834 --- /dev/null +++ b/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.hashing; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class Keccak256HashingUnitTest { + + private static String originalValue = "abc123"; + private static String hashedValue = "719accc61a9cc126830e5906f9d672d06eab6f8597287095a2c55a8b775e7016"; + + @Test public void testHashWithJavaMessageDigest() throws Exception { + final String currentHashedValue = Keccak256Hashing.hashWithJavaMessageDigest(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + @Test public void testHashWithBouncyCastle() { + final String currentHashedValue = Keccak256Hashing.hashWithBouncyCastle(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + +} diff --git a/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java b/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java index 3c34bf2c6e..6bc9ad2cc6 100644 --- a/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java +++ b/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java @@ -12,24 +12,24 @@ public class SHA256HashingUnitTest { @Test public void testHashWithJavaMessageDigest() throws Exception { final String currentHashedValue = SHA256Hashing.HashWithJavaMessageDigest(originalValue); - assertEquals(currentHashedValue, hashedValue); + assertEquals(hashedValue, currentHashedValue); } @Test public void testHashWithGuava() throws Exception { - final String currentHashedValue = SHA256Hashing.HashWithApacheCommons(originalValue); - assertEquals(currentHashedValue, hashedValue); + final String currentHashedValue = SHA256Hashing.hashWithGuava(originalValue); + assertEquals(hashedValue, currentHashedValue); } @Test public void testHashWithApacheCommans() throws Exception { - final String currentHashedValue = SHA256Hashing.HashWithGuava(originalValue); - assertEquals(currentHashedValue, hashedValue); + final String currentHashedValue = SHA256Hashing.HashWithApacheCommons(originalValue); + assertEquals(hashedValue, currentHashedValue); } @Test public void testHashWithBouncyCastle() throws Exception { final String currentHashedValue = SHA256Hashing.HashWithBouncyCastle(originalValue); - assertEquals(currentHashedValue, hashedValue); + assertEquals(hashedValue, currentHashedValue); } } \ No newline at end of file diff --git a/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java b/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java new file mode 100644 index 0000000000..fffab96405 --- /dev/null +++ b/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.hashing; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SHA3HashingUnitTest { + + private static String originalValue = "abc123"; + private static String hashedValue = "f58fa3df820114f56e1544354379820cff464c9c41cb3ca0ad0b0843c9bb67ee"; + + /* works with JDK9+ only */ + //@Test + public void testHashWithJavaMessageDigestJDK9() throws Exception { + final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigestJDK9(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + @Test + public void testHashWithJavaMessageDigest() throws Exception { + final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigest(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + /* works with JDK9+ only */ + //@Test + public void testHashWithApacheCommonsJDK9() { + final String currentHashedValue = SHA3Hashing.hashWithApacheCommonsJDK9(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + @Test + public void testHashWithBouncyCastle() { + final String currentHashedValue = SHA3Hashing.hashWithBouncyCastle(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + +} diff --git a/core-java/README.md b/core-java/README.md index 5aee69d9a9..d2fd903c10 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -46,3 +46,8 @@ - [Graphs in Java](https://www.baeldung.com/java-graphs) - [Console I/O in Java](http://www.baeldung.com/java-console-input-output) - [Formatting with printf() in Java](https://www.baeldung.com/java-printstream-printf) +- [Retrieve Fields from a Java Class Using Reflection](https://www.baeldung.com/java-reflection-class-fields) +- [Introduction to Basic Syntax in Java](https://www.baeldung.com/java-syntax) +- [Using Curl in Java](https://www.baeldung.com/java-curl) +- [Finding Leap Years in Java](https://www.baeldung.com/java-leap-year) +- [Java Bitwise Operators](https://www.baeldung.com/java-bitwise-operators) diff --git a/core-java/src/main/java/com/baeldung/jar/JarExample.java b/core-java/src/main/java/com/baeldung/jar/JarExample.java new file mode 100644 index 0000000000..5f33188adf --- /dev/null +++ b/core-java/src/main/java/com/baeldung/jar/JarExample.java @@ -0,0 +1,9 @@ +package com.baeldung.jar; + +public class JarExample { + + public static void main(String[] args) { + System.out.println("Hello Baeldung Reader!"); + } + +} diff --git a/core-java/src/main/java/com/baeldung/jar/example_manifest.txt b/core-java/src/main/java/com/baeldung/jar/example_manifest.txt new file mode 100644 index 0000000000..90e83e9b42 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/jar/example_manifest.txt @@ -0,0 +1 @@ +Main-Class: com.baeldung.jar.JarExample diff --git a/core-kotlin/README.md b/core-kotlin/README.md index 225ad87e87..6ee79b2a2e 100644 --- a/core-kotlin/README.md +++ b/core-kotlin/README.md @@ -51,3 +51,4 @@ - [Operator Overloading in Kotlin](https://www.baeldung.com/kotlin-operator-overloading) - [Inline Classes in Kotlin](https://www.baeldung.com/kotlin-inline-classes) - [Creating Java static final Equivalents in Kotlin](https://www.baeldung.com/kotlin-java-static-final) +- [Nested forEach in Kotlin](https://www.baeldung.com/kotlin-nested-foreach) diff --git a/guice/pom.xml b/guice/pom.xml index f3e7873245..5c4518da7a 100644 --- a/guice/pom.xml +++ b/guice/pom.xml @@ -26,4 +26,4 @@ 4.1.0 - + \ No newline at end of file diff --git a/guice/src/main/java/com/baeldung/examples/common/Account.java b/guice/src/main/java/com/baeldung/examples/common/Account.java new file mode 100644 index 0000000000..fd2df005ac --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/Account.java @@ -0,0 +1,24 @@ +package com.baeldung.examples.common; + +public class Account { + + private String accountNumber; + private String type; + + public String getAccountNumber() { + return accountNumber; + } + + public void setAccountNumber(String accountNumber) { + this.accountNumber = accountNumber; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AccountService.java b/guice/src/main/java/com/baeldung/examples/common/AccountService.java new file mode 100644 index 0000000000..97a64e3c6e --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AccountService.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public interface AccountService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AccountServiceImpl.java b/guice/src/main/java/com/baeldung/examples/common/AccountServiceImpl.java new file mode 100644 index 0000000000..18d6777c4a --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AccountServiceImpl.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public class AccountServiceImpl implements AccountService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AudioBookService.java b/guice/src/main/java/com/baeldung/examples/common/AudioBookService.java new file mode 100644 index 0000000000..5d501f2051 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AudioBookService.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public interface AudioBookService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AudioBookServiceImpl.java b/guice/src/main/java/com/baeldung/examples/common/AudioBookServiceImpl.java new file mode 100644 index 0000000000..c64e953a58 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AudioBookServiceImpl.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public class AudioBookServiceImpl implements AudioBookService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AuthorService.java b/guice/src/main/java/com/baeldung/examples/common/AuthorService.java new file mode 100644 index 0000000000..9be148b8c3 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AuthorService.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public interface AuthorService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AuthorServiceImpl.java b/guice/src/main/java/com/baeldung/examples/common/AuthorServiceImpl.java new file mode 100644 index 0000000000..bac532e469 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AuthorServiceImpl.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public class AuthorServiceImpl implements AuthorService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/BookService.java b/guice/src/main/java/com/baeldung/examples/common/BookService.java new file mode 100644 index 0000000000..56339c1398 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/BookService.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public interface BookService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/BookServiceImpl.java b/guice/src/main/java/com/baeldung/examples/common/BookServiceImpl.java new file mode 100644 index 0000000000..aee0d22e51 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/BookServiceImpl.java @@ -0,0 +1,7 @@ +package com.baeldung.examples.common; + +public class BookServiceImpl implements BookService { + + private AuthorService authorService; + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/PersonDao.java b/guice/src/main/java/com/baeldung/examples/common/PersonDao.java new file mode 100644 index 0000000000..980fee0252 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/PersonDao.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public interface PersonDao { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java b/guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java new file mode 100644 index 0000000000..ecbf198cc0 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public class PersonDaoImpl implements PersonDao { + +} \ No newline at end of file diff --git a/guice/src/main/java/com/baeldung/examples/guice/Foo.java b/guice/src/main/java/com/baeldung/examples/guice/Foo.java new file mode 100644 index 0000000000..fca32b165b --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/Foo.java @@ -0,0 +1,4 @@ +package com.baeldung.examples.guice; + +public class Foo { +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/FooProcessor.java b/guice/src/main/java/com/baeldung/examples/guice/FooProcessor.java new file mode 100644 index 0000000000..929013cd2b --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/FooProcessor.java @@ -0,0 +1,9 @@ +package com.baeldung.examples.guice; + +import com.google.inject.Inject; + +public class FooProcessor { + + @Inject + private Foo foo; +} \ No newline at end of file diff --git a/guice/src/main/java/com/baeldung/examples/guice/GuicePersonService.java b/guice/src/main/java/com/baeldung/examples/guice/GuicePersonService.java new file mode 100644 index 0000000000..ce12e3e528 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/GuicePersonService.java @@ -0,0 +1,19 @@ +package com.baeldung.examples.guice; + +import com.baeldung.examples.common.PersonDao; +import com.google.inject.Inject; + +public class GuicePersonService { + + @Inject + private PersonDao personDao; + + public PersonDao getPersonDao() { + return personDao; + } + + public void setPersonDao(PersonDao personDao) { + this.personDao = personDao; + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/GuiceUserService.java b/guice/src/main/java/com/baeldung/examples/guice/GuiceUserService.java new file mode 100644 index 0000000000..0e58d0bacf --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/GuiceUserService.java @@ -0,0 +1,19 @@ +package com.baeldung.examples.guice; + +import com.baeldung.examples.common.AccountService; +import com.google.inject.Inject; + +public class GuiceUserService { + + @Inject + private AccountService accountService; + + public AccountService getAccountService() { + return accountService; + } + + public void setAccountService(AccountService accountService) { + this.accountService = accountService; + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/Person.java b/guice/src/main/java/com/baeldung/examples/guice/Person.java new file mode 100644 index 0000000000..d54b5110eb --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/Person.java @@ -0,0 +1,24 @@ +package com.baeldung.examples.guice; + +public class Person { + private String firstName; + + private String lastName; + + 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; + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/modules/GuiceModule.java b/guice/src/main/java/com/baeldung/examples/guice/modules/GuiceModule.java new file mode 100644 index 0000000000..fbcd36b56a --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/modules/GuiceModule.java @@ -0,0 +1,50 @@ +package com.baeldung.examples.guice.modules; + +import com.baeldung.examples.common.AccountService; +import com.baeldung.examples.common.AccountServiceImpl; +import com.baeldung.examples.common.BookService; +import com.baeldung.examples.common.BookServiceImpl; +import com.baeldung.examples.common.PersonDao; +import com.baeldung.examples.common.PersonDaoImpl; +import com.baeldung.examples.guice.Foo; +import com.baeldung.examples.guice.Person; +import com.google.inject.AbstractModule; +import com.google.inject.Provider; +import com.google.inject.Provides; + +public class GuiceModule extends AbstractModule { + + @Override + protected void configure() { + try { + bind(AccountService.class).to(AccountServiceImpl.class); + bind(Person.class).toConstructor(Person.class.getConstructor()); + // bind(Person.class).toProvider(new Provider() { + // public Person get() { + // Person p = new Person(); + // return p; + // } + // }); + bind(Foo.class).toProvider(new Provider() { + public Foo get() { + return new Foo(); + } + }); + bind(PersonDao.class).to(PersonDaoImpl.class); + + } catch (NoSuchMethodException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + @Provides + public BookService bookServiceGenerator() { + return new BookServiceImpl(); + } + +} diff --git a/guice/src/test/java/com/baeldung/examples/GuiceUnitTest.java b/guice/src/test/java/com/baeldung/examples/GuiceUnitTest.java new file mode 100644 index 0000000000..dd2a89e101 --- /dev/null +++ b/guice/src/test/java/com/baeldung/examples/GuiceUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.examples; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +import com.baeldung.examples.common.BookService; +import com.baeldung.examples.guice.FooProcessor; +import com.baeldung.examples.guice.GuicePersonService; +import com.baeldung.examples.guice.GuiceUserService; +import com.baeldung.examples.guice.Person; +import com.baeldung.examples.guice.modules.GuiceModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +public class GuiceUnitTest { + + @Test + public void givenAccountServiceInjectedInGuiceUserService_WhenGetAccountServiceInvoked_ThenReturnValueIsNotNull() { + Injector injector = Guice.createInjector(new GuiceModule()); + GuiceUserService guiceUserService = injector.getInstance(GuiceUserService.class); + assertNotNull(guiceUserService.getAccountService()); + } + + @Test + public void givenBookServiceIsRegisteredInModule_WhenBookServiceIsInjected_ThenReturnValueIsNotNull() { + Injector injector = Guice.createInjector(new GuiceModule()); + BookService bookService = injector.getInstance(BookService.class); + assertNotNull(bookService); + } + + @Test + public void givenMultipleBindingsForPerson_WhenPersonIsInjected_ThenTestFailsByProvisionException() { + Injector injector = Guice.createInjector(new GuiceModule()); + Person person = injector.getInstance(Person.class); + assertNotNull(person); + } + + @Test + public void givenFooInjectedToFooProcessorAsOptionalDependency_WhenFooProcessorIsRetrievedFromContext_ThenCreationExceptionIsNotThrown() { + Injector injector = Guice.createInjector(new GuiceModule()); + FooProcessor fooProcessor = injector.getInstance(FooProcessor.class); + assertNotNull(fooProcessor); + } + + @Test + public void givenGuicePersonServiceConstructorAnnotatedByInject_WhenGuicePersonServiceIsInjected_ThenInstanceWillBeCreatedFromTheConstructor() { + Injector injector = Guice.createInjector(new GuiceModule()); + GuicePersonService personService = injector.getInstance(GuicePersonService.class); + assertNotNull(personService); + } + + @Test + public void givenPersonDaoInjectedToGuicePersonServiceBySetterInjection_WhenGuicePersonServiceIsInjected_ThenPersonDaoInitializedByTheSetter() { + Injector injector = Guice.createInjector(new GuiceModule()); + GuicePersonService personService = injector.getInstance(GuicePersonService.class); + assertNotNull(personService); + assertNotNull(personService.getPersonDao()); + } + +} diff --git a/jackson/README.md b/jackson/README.md index 04e88d0ea1..e201a06727 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -37,3 +37,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Serialize Only Fields that meet a Custom Criteria with Jackson](http://www.baeldung.com/jackson-serialize-field-custom-criteria) - [Mapping Nested Values with Jackson](http://www.baeldung.com/jackson-nested-values) - [Convert XML to JSON Using Jackson](https://www.baeldung.com/jackson-convert-xml-json) +- [Deserialize Immutable Objects with Jackson](https://www.baeldung.com/jackson-deserialize-immutable-objects) diff --git a/java-collections-maps/README.md b/java-collections-maps/README.md index b4ab270448..5d65e961de 100644 --- a/java-collections-maps/README.md +++ b/java-collections-maps/README.md @@ -19,3 +19,4 @@ - [How to Check If a Key Exists in a Map](https://www.baeldung.com/java-map-key-exists) - [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps) - [Immutable Map Implementations in Java](https://www.baeldung.com/java-immutable-maps) +- [Map to String Conversion in Java](https://www.baeldung.com/java-map-to-string-conversion) diff --git a/java-dates/README.md b/java-dates/README.md index ac3166d938..8171e5def9 100644 --- a/java-dates/README.md +++ b/java-dates/README.md @@ -27,4 +27,5 @@ - [Convert Between java.time.Instant and java.sql.Timestamp](https://www.baeldung.com/java-time-instant-to-java-sql-timestamp) - [Convert between String and Timestamp](https://www.baeldung.com/java-string-to-timestamp) - [A Guide to SimpleDateFormat](https://www.baeldung.com/java-simple-date-format) -- [ZoneOffset in Java](https://www.baeldung.com/java-zone-offset) \ No newline at end of file +- [ZoneOffset in Java](https://www.baeldung.com/java-zone-offset) +- [Differences Between ZonedDateTime and OffsetDateTime](https://www.baeldung.com/java-zoneddatetime-offsetdatetime) diff --git a/java-streams/README.md b/java-streams/README.md index 33ca2619a8..15ea1c742a 100644 --- a/java-streams/README.md +++ b/java-streams/README.md @@ -15,3 +15,5 @@ - [Stream Ordering in Java](https://www.baeldung.com/java-stream-ordering) - [Introduction to Protonpack](https://www.baeldung.com/java-protonpack) - [Java Stream Filter with Lambda Expression](https://www.baeldung.com/java-stream-filter-lambda) +- [Counting Matches on a Stream Filter](https://www.baeldung.com/java-stream-filter-count) +- [Java 8 Streams peek() API](https://www.baeldung.com/java-streams-peek-api) diff --git a/java-strings/README.md b/java-strings/README.md index b72a378d06..1ab5e098f6 100644 --- a/java-strings/README.md +++ b/java-strings/README.md @@ -50,3 +50,6 @@ - [Remove Leading and Trailing Characters from a String](https://www.baeldung.com/java-remove-trailing-characters) - [Concatenating Strings In Java](https://www.baeldung.com/java-strings-concatenation) - [Java toString() Method](https://www.baeldung.com/java-tostring) +- [Java String Interview Questions and Answers](https://www.baeldung.com/java-string-interview-questions) +- [Check if a String is a Pangram in Java](https://www.baeldung.com/java-string-pangram) +- [Check If a String Contains Multiple Keywords](https://www.baeldung.com/string-contains-multiple-words) diff --git a/jooby/src/test/java/com/baeldung/jooby/AppLiveTest.java b/jooby/src/test/java/com/baeldung/jooby/AppLiveTest.java new file mode 100644 index 0000000000..1bd12f8bb3 --- /dev/null +++ b/jooby/src/test/java/com/baeldung/jooby/AppLiveTest.java @@ -0,0 +1,21 @@ +package com.baeldung.jooby; + +import static io.restassured.RestAssured.get; +import static org.hamcrest.Matchers.equalTo; + +import org.jooby.test.JoobyRule; +import org.junit.ClassRule; +import org.junit.Test; + +public class AppLiveTest { + + @ClassRule + public static JoobyRule app = new JoobyRule(new App()); + + @Test + public void given_defaultUrl_expect_fixedString() { + get("/").then().assertThat().body(equalTo("Hello World!")).statusCode(200) + .contentType("text/html;charset=UTF-8"); + } + +} diff --git a/jooby/src/test/java/com/baeldung/jooby/AppUnitTest.java b/jooby/src/test/java/com/baeldung/jooby/AppUnitTest.java index ab7388f5f4..9bca30e2c1 100644 --- a/jooby/src/test/java/com/baeldung/jooby/AppUnitTest.java +++ b/jooby/src/test/java/com/baeldung/jooby/AppUnitTest.java @@ -1,25 +1,12 @@ package com.baeldung.jooby; -import static io.restassured.RestAssured.get; -import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertEquals; -import org.jooby.test.JoobyRule; import org.jooby.test.MockRouter; -import org.junit.ClassRule; import org.junit.Test; public class AppUnitTest { - @ClassRule - public static JoobyRule app = new JoobyRule(new App()); - - @Test - public void given_defaultUrl_expect_fixedString() { - get("/").then().assertThat().body(equalTo("Hello World!")).statusCode(200) - .contentType("text/html;charset=UTF-8"); - } - @Test public void given_defaultUrl_with_mockrouter_expect_fixedString() throws Throwable { String result = new MockRouter(new App()).get("/"); diff --git a/kotlin-libraries/README.md b/kotlin-libraries/README.md index 4110bfe12e..5e2526e64e 100644 --- a/kotlin-libraries/README.md +++ b/kotlin-libraries/README.md @@ -9,3 +9,4 @@ - [Working with Dates in Kotlin](https://www.baeldung.com/kotlin-dates) - [Introduction to Arrow in Kotlin](https://www.baeldung.com/kotlin-arrow) - [Kotlin with Ktor](https://www.baeldung.com/kotlin-ktor) +- [REST API With Kotlin and Kovert](https://www.baeldung.com/kotlin-kovert) diff --git a/libraries-server/README.md b/libraries-server/README.md index 28f963ade8..75c12fd61a 100644 --- a/libraries-server/README.md +++ b/libraries-server/README.md @@ -7,3 +7,4 @@ - [Creating and Configuring Jetty 9 Server in Java](http://www.baeldung.com/jetty-java-programmatic) - [Testing Netty with EmbeddedChannel](http://www.baeldung.com/testing-netty-embedded-channel) - [MQTT Client in Java](https://www.baeldung.com/java-mqtt-client) +- [Guide to XMPP Smack Client](https://www.baeldung.com/xmpp-smack-chat-client) diff --git a/libraries/README.md b/libraries/README.md index b247caedda..378317778e 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -64,7 +64,8 @@ - [Exactly Once Processing in Kafka](https://www.baeldung.com/kafka-exactly-once) - [An Introduction to SuanShu](https://www.baeldung.com/suanshu) - [Implementing a FTP-Client in Java](http://www.baeldung.com/java-ftp-client) -- [Introduction to Functional Java](https://www.baeldung.com/java-functional-library +- [Introduction to Functional Java](https://www.baeldung.com/java-functional-library) +- [Intro to Derive4J](https://www.baeldung.com/derive4j) The libraries module contains examples related to small libraries that are relatively easy to use and does not require any separate module of its own. diff --git a/mapstruct/pom.xml b/mapstruct/pom.xml index 6c274dfcf2..0493775f85 100644 --- a/mapstruct/pom.xml +++ b/mapstruct/pom.xml @@ -30,6 +30,11 @@ ${springframework.version} test + + org.projectlombok + lombok + ${org.projectlombok.version} + @@ -48,6 +53,11 @@ mapstruct-processor ${org.mapstruct.version} + + org.projectlombok + lombok + ${org.projectlombok.version} + @@ -55,10 +65,11 @@ - 1.1.0.Final + 1.3.0.Beta2 4.3.4.RELEASE 1.8 1.8 + 1.18.4 diff --git a/mapstruct/src/main/java/com/baeldung/dto/CarDTO.java b/mapstruct/src/main/java/com/baeldung/dto/CarDTO.java new file mode 100644 index 0000000000..51aa8ccac2 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/dto/CarDTO.java @@ -0,0 +1,11 @@ +package com.baeldung.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CarDTO { + private int id; + private String name; +} diff --git a/mapstruct/src/main/java/com/baeldung/dto/PersonDTO.java b/mapstruct/src/main/java/com/baeldung/dto/PersonDTO.java new file mode 100644 index 0000000000..ace7a2bc7d --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/dto/PersonDTO.java @@ -0,0 +1,33 @@ +package com.baeldung.dto; + +public class PersonDTO { + + private String id; + private String name; + + public PersonDTO() { + + } + + public PersonDTO(String id, String name) { + super(); + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/mapstruct/src/main/java/com/baeldung/entity/Car.java b/mapstruct/src/main/java/com/baeldung/entity/Car.java new file mode 100644 index 0000000000..8559b4a77d --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/entity/Car.java @@ -0,0 +1,11 @@ +package com.baeldung.entity; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class Car { + private int id; + private String name; +} diff --git a/mapstruct/src/main/java/com/baeldung/entity/Person.java b/mapstruct/src/main/java/com/baeldung/entity/Person.java new file mode 100644 index 0000000000..5f73ee1130 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/entity/Person.java @@ -0,0 +1,33 @@ +package com.baeldung.entity; + +public class Person { + + private String id; + private String name; + + public Person() { + + } + + public Person(String id, String name) { + super(); + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/mapstruct/src/main/java/com/baeldung/mapper/CarMapper.java b/mapstruct/src/main/java/com/baeldung/mapper/CarMapper.java new file mode 100644 index 0000000000..c18fa44f8d --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapper/CarMapper.java @@ -0,0 +1,15 @@ +package com.baeldung.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.baeldung.dto.CarDTO; +import com.baeldung.entity.Car; + +@Mapper +public interface CarMapper { + + CarMapper INSTANCE = Mappers.getMapper(CarMapper.class); + + CarDTO carToCarDTO(Car car); +} diff --git a/mapstruct/src/main/java/com/baeldung/mapper/PersonMapper.java b/mapstruct/src/main/java/com/baeldung/mapper/PersonMapper.java new file mode 100644 index 0000000000..9b9e132b5d --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapper/PersonMapper.java @@ -0,0 +1,17 @@ +package com.baeldung.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +import com.baeldung.dto.PersonDTO; +import com.baeldung.entity.Person; + +@Mapper +public interface PersonMapper { + + PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class); + + @Mapping(target = "id", source = "person.id", defaultExpression = "java(java.util.UUID.randomUUID().toString())") + PersonDTO personToPersonDTO(Person person); +} diff --git a/mapstruct/src/test/java/com/baeldung/mapper/CarMapperUnitTest.java b/mapstruct/src/test/java/com/baeldung/mapper/CarMapperUnitTest.java new file mode 100644 index 0000000000..32cae56c2e --- /dev/null +++ b/mapstruct/src/test/java/com/baeldung/mapper/CarMapperUnitTest.java @@ -0,0 +1,24 @@ +package com.baeldung.mapper; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.baeldung.dto.CarDTO; +import com.baeldung.entity.Car; + +public class CarMapperUnitTest { + + @Test + public void givenCarEntitytoCar_whenMaps_thenCorrect() { + + Car entity = new Car(); + entity.setId(1); + entity.setName("Toyota"); + + CarDTO carDto = CarMapper.INSTANCE.carToCarDTO(entity); + + assertEquals(carDto.getId(), entity.getId()); + assertEquals(carDto.getName(), entity.getName()); + } +} diff --git a/mapstruct/src/test/java/com/baeldung/mapper/PersonMapperUnitTest.java b/mapstruct/src/test/java/com/baeldung/mapper/PersonMapperUnitTest.java new file mode 100644 index 0000000000..fe4c52ac89 --- /dev/null +++ b/mapstruct/src/test/java/com/baeldung/mapper/PersonMapperUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.mapper; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +import com.baeldung.dto.PersonDTO; +import com.baeldung.entity.Person; + +public class PersonMapperUnitTest { + + @Test + public void givenPersonEntitytoPersonWithExpression_whenMaps_thenCorrect() { + + Person entity = new Person(); + entity.setName("Micheal"); + + PersonDTO personDto = PersonMapper.INSTANCE.personToPersonDTO(entity); + + assertNull(entity.getId()); + assertNotNull(personDto.getId()); + assertEquals(personDto.getName(), entity.getName()); + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate5/README.md b/persistence-modules/hibernate5/README.md index 03bdd9b759..a4e95a9062 100644 --- a/persistence-modules/hibernate5/README.md +++ b/persistence-modules/hibernate5/README.md @@ -29,3 +29,4 @@ - [Hibernate Named Query](https://www.baeldung.com/hibernate-named-query) - [Using c3p0 with Hibernate](https://www.baeldung.com/hibernate-c3p0) - [Persist a JSON Object Using Hibernate](https://www.baeldung.com/hibernate-persist-json-object) +- [Common Hibernate Exceptions](https://www.baeldung.com/hibernate-exceptions) diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Student.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Student.java index a6dec4a30d..9b26c117eb 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Student.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Student.java @@ -9,15 +9,43 @@ import javax.persistence.Id; public class Student { @Id - @GeneratedValue (strategy = GenerationType.SEQUENCE) + @GeneratedValue(strategy = GenerationType.SEQUENCE) private long studentId; + private String name; + + private int age; + + public Student() { + } + + public Student(String name, int age) { + this.name = name; + this.age = age; + } + public long getStudentId() { return studentId; } - public void setStudent_id(long studentId) { + public void setStudentId(long studentId) { this.studentId = studentId; } - + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + } diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/aggregatefunctions/AggregateFunctionsIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/aggregatefunctions/AggregateFunctionsIntegrationTest.java new file mode 100644 index 0000000000..0b2bdf7ead --- /dev/null +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/aggregatefunctions/AggregateFunctionsIntegrationTest.java @@ -0,0 +1,87 @@ +package com.baeldung.hibernate.aggregatefunctions; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; + +import org.hibernate.HibernateException; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baeldung.hibernate.HibernateUtil; +import com.baeldung.hibernate.pojo.Student; + +public class AggregateFunctionsIntegrationTest { + + private static Session session; + private static Transaction transaction; + + @BeforeClass + public static final void setup() throws HibernateException, IOException { + session = HibernateUtil.getSessionFactory() + .openSession(); + transaction = session.beginTransaction(); + + Student jonas = new Student("Jonas", 22); + session.save(jonas); + + Student sally = new Student("Sally", 20); + session.save(sally); + + Student simon = new Student("Simon", 25); + session.save(simon); + + Student raven = new Student("Raven", 21); + session.save(raven); + + Student sam = new Student("Sam", 23); + session.save(sam); + + } + + @AfterClass + public static final void teardown() { + if (session != null) { + transaction.rollback(); + session.close(); + } + } + + @Test + public void whenMaxAge_ThenReturnValue() { + int maxAge = (int) session.createQuery("SELECT MAX(age) from Student") + .getSingleResult(); + assertThat(maxAge).isEqualTo(25); + } + + @Test + public void whenMinAge_ThenReturnValue() { + int minAge = (int) session.createQuery("SELECT MIN(age) from Student") + .getSingleResult(); + assertThat(minAge).isEqualTo(20); + } + + @Test + public void whenAverageAge_ThenReturnValue() { + Double avgAge = (Double) session.createQuery("SELECT AVG(age) from Student") + .getSingleResult(); + assertThat(avgAge).isEqualTo(22.2); + } + + @Test + public void whenCountAll_ThenReturnValue() { + Long totalStudents = (Long) session.createQuery("SELECT COUNT(*) from Student") + .getSingleResult(); + assertThat(totalStudents).isEqualTo(5); + } + + @Test + public void whenSumOfAllAges_ThenReturnValue() { + Long sumOfAllAges = (Long) session.createQuery("SELECT SUM(age) from Student") + .getSingleResult(); + assertThat(sumOfAllAges).isEqualTo(111); + } +} diff --git a/persistence-modules/java-jpa/README.md b/persistence-modules/java-jpa/README.md index 2eea5e60b4..2c26581bab 100644 --- a/persistence-modules/java-jpa/README.md +++ b/persistence-modules/java-jpa/README.md @@ -4,3 +4,5 @@ - [A Guide to Stored Procedures with JPA](http://www.baeldung.com/jpa-stored-procedures) - [Fixing the JPA error “java.lang.String cannot be cast to Ljava.lang.String;”](https://www.baeldung.com/jpa-error-java-lang-string-cannot-be-cast) - [JPA Entity Graph](https://www.baeldung.com/jpa-entity-graph) +- [JPA 2.2 Support for Java 8 Date/Time Types](https://www.baeldung.com/jpa-java-time) +- [Converting Between LocalDate and SQL Date](https://www.baeldung.com/java-convert-localdate-sql-date) diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/test/java/com/baeldung/SpringContextIntegrationTest.java new file mode 100644 index 0000000000..cf964b5011 --- /dev/null +++ b/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -0,0 +1,19 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.test.context.web.WebAppConfiguration; + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class) +@WebAppConfiguration +public class SpringContextIntegrationTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/persistence-modules/spring-boot-persistence/README.MD b/persistence-modules/spring-boot-persistence/README.MD index cab6be1ec8..6fe5e6f05f 100644 --- a/persistence-modules/spring-boot-persistence/README.MD +++ b/persistence-modules/spring-boot-persistence/README.MD @@ -6,4 +6,4 @@ - [Configuring a Tomcat Connection Pool in Spring Boot](https://www.baeldung.com/spring-boot-tomcat-connection-pool) - [Hibernate Field Naming with Spring Boot](https://www.baeldung.com/hibernate-field-naming-spring-boot) - [Integrating Spring Boot with HSQLDB](https://www.baeldung.com/spring-boot-hsqldb) - +- [Configuring a DataSource Programmatically in Spring Boot](https://www.baeldung.com/spring-boot-configure-data-source-programmatic) diff --git a/persistence-modules/spring-data-jpa/README.md b/persistence-modules/spring-data-jpa/README.md index 976a692699..739031ff5e 100644 --- a/persistence-modules/spring-data-jpa/README.md +++ b/persistence-modules/spring-data-jpa/README.md @@ -19,6 +19,7 @@ - [Sorting Query Results with Spring Data](https://www.baeldung.com/spring-data-sorting) - [INSERT Statement in JPA](https://www.baeldung.com/jpa-insert) - [Pagination and Sorting using Spring Data JPA](https://www.baeldung.com/spring-data-jpa-pagination-sorting) +- [Spring Data JPA Query by Example](https://www.baeldung.com/spring-data-query-by-example) ### Eclipse Config After importing the project into Eclipse, you may see the following error: diff --git a/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java b/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java index 723b097305..c3805bac57 100644 --- a/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java +++ b/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java @@ -1,17 +1,24 @@ package com.baeldung.hibernate.criteria; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.util.List; import org.hibernate.Session; +import org.hibernate.Transaction; import org.junit.Test; import com.baeldung.hibernate.criteria.model.Item; import com.baeldung.hibernate.criteria.util.HibernateUtil; import com.baeldung.hibernate.criteria.view.ApplicationView; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaDelete; +import javax.persistence.criteria.CriteriaUpdate; +import javax.persistence.criteria.Root; + public class HibernateCriteriaIntegrationTest { final private ApplicationView av = new ApplicationView(); @@ -179,4 +186,51 @@ public class HibernateCriteriaIntegrationTest { session.close(); assertArrayEquals(expectedPriceBetweenItems, av.betweenCriteria()); } + + @Test + public void givenNewItemPrice_whenCriteriaUpdate_thenReturnAffectedResult() { + + int oldPrice = 10, newPrice = 20; + + Session session = HibernateUtil.getHibernateSession(); + + Item item = new Item(12, "Test Item 12", "This is a description"); + item.setItemPrice(oldPrice); + session.save(item); + + CriteriaBuilder cb = session.getCriteriaBuilder(); + CriteriaUpdate criteriaUpdate = cb.createCriteriaUpdate(Item.class); + Root root = criteriaUpdate.from(Item.class); + criteriaUpdate.set("itemPrice", newPrice); + criteriaUpdate.where(cb.equal(root.get("itemPrice"), oldPrice)); + + Transaction transaction = session.beginTransaction(); + session.createQuery(criteriaUpdate).executeUpdate(); + transaction.commit(); + + Item updatedItem = session.createQuery("FROM Item WHERE itemPrice = " + newPrice, Item.class).getSingleResult(); + session.refresh(updatedItem); + assertEquals(newPrice, updatedItem.getItemPrice().intValue()); + } + + @Test + public void givenTargetItemPrice_whenCriteriaDelete_thenDeleteMatched() { + + int targetPrice = 1000; + + Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder cb = session.getCriteriaBuilder(); + CriteriaDelete criteriaDelete = cb.createCriteriaDelete(Item.class); + Root root = criteriaDelete.from(Item.class); + criteriaDelete.where(cb.greaterThan(root.get("itemPrice"), targetPrice)); + + Transaction transaction = session.beginTransaction(); + session.createQuery(criteriaDelete).executeUpdate(); + transaction.commit(); + + List deletedItem = session.createQuery("FROM Item WHERE itemPrice > " + targetPrice, Item.class).list(); + assertTrue(deletedItem.isEmpty()); + + } + } diff --git a/persistence-modules/spring-jpa/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/persistence-modules/spring-jpa/src/test/java/com/baeldung/SpringContextIntegrationTest.java new file mode 100644 index 0000000000..aa85128628 --- /dev/null +++ b/persistence-modules/spring-jpa/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -0,0 +1,19 @@ +package com.baeldung; + +import org.baeldung.config.PersistenceJPAConfigL2Cache; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfigL2Cache.class }, loader = AnnotationConfigContextLoader.class) +@WebAppConfiguration +public class SpringContextIntegrationTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/pom.xml b/pom.xml index 787a03c2fb..58d57ade05 100644 --- a/pom.xml +++ b/pom.xml @@ -733,6 +733,7 @@ spring-security-mvc-boot spring-security-mvc-custom spring-security-mvc-digest-auth + spring-security-mvc-jsonview spring-security-mvc-ldap spring-security-mvc-login spring-security-mvc-persisted-remember-me diff --git a/spring-4/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-4/src/test/java/org/baeldung/SpringContextIntegrationTest.java index 9dfac2bd9e..d646e22511 100644 --- a/spring-4/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/spring-4/src/test/java/org/baeldung/SpringContextIntegrationTest.java @@ -2,13 +2,16 @@ package org.baeldung; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; import com.baeldung.flips.ApplicationConfig; -@RunWith(SpringRunner.class) -@SpringBootTest(classes = ApplicationConfig.class) + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = ApplicationConfig.class) +@WebAppConfiguration public class SpringContextIntegrationTest { @Test diff --git a/spring-5-reactive-oauth/README.md b/spring-5-reactive-oauth/README.md index 0f27cf5d20..ec5176670b 100644 --- a/spring-5-reactive-oauth/README.md +++ b/spring-5-reactive-oauth/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Spring Security OAuth Login with WebFlux](https://www.baeldung.com/spring-oauth-login-webflux) +- [Spring WebClient and OAuth2 Support](https://www.baeldung.com/spring-webclient-oauth2) diff --git a/spring-5-reactive-oauth/pom.xml b/spring-5-reactive-oauth/pom.xml index 73809681f2..4e05227c6c 100644 --- a/spring-5-reactive-oauth/pom.xml +++ b/spring-5-reactive-oauth/pom.xml @@ -62,11 +62,11 @@ org.apache.maven.plugins maven-surefire-plugin - 2.20.1 true **/*IntegrationTest.java + **/*LiveTest.java diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/SpringContextLiveTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/SpringContextLiveTest.java new file mode 100644 index 0000000000..494013d1d9 --- /dev/null +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/SpringContextLiveTest.java @@ -0,0 +1,19 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import com.baeldung.autoconfiguration.MySQLAutoconfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = MySQLAutoconfiguration.class) +@WebAppConfiguration +public class SpringContextLiveTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} \ No newline at end of file diff --git a/spring-boot-bootstrap/README.md b/spring-boot-bootstrap/README.md index 76b977c129..2186aa8fec 100644 --- a/spring-boot-bootstrap/README.md +++ b/spring-boot-bootstrap/README.md @@ -5,3 +5,4 @@ - [Deploying a Spring Boot Application to Cloud Foundry](https://www.baeldung.com/spring-boot-app-deploy-to-cloud-foundry) - [Deploy a Spring Boot Application to Google App Engine](https://www.baeldung.com/spring-boot-google-app-engine) - [Deploy a Spring Boot Application to OpenShift](https://www.baeldung.com/spring-boot-deploy-openshift) +- [Deploy a Spring Boot Application to AWS Beanstalk](https://www.baeldung.com/spring-boot-deploy-aws-beanstalk) diff --git a/spring-boot-mvc/README.md b/spring-boot-mvc/README.md index bf32e4fc7c..0e1ac5a8ce 100644 --- a/spring-boot-mvc/README.md +++ b/spring-boot-mvc/README.md @@ -9,4 +9,5 @@ - [Display RSS Feed with Spring MVC](http://www.baeldung.com/spring-mvc-rss-feed) - [A Controller, Service and DAO Example with Spring Boot and JSF](https://www.baeldung.com/jsf-spring-boot-controller-service-dao) - [Cache Eviction in Spring Boot](https://www.baeldung.com/spring-boot-evict-cache) -- [Setting Up Swagger 2 with a Spring REST API](http://www.baeldung.com/swagger-2-documentation-for-spring-rest-api) \ No newline at end of file +- [Setting Up Swagger 2 with a Spring REST API](http://www.baeldung.com/swagger-2-documentation-for-spring-rest-api) +- [Conditionally Enable Scheduled Jobs in Spring](https://www.baeldung.com/spring-scheduled-enabled-conditionally) diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index 2c89a64a00..15e80ec515 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -2,4 +2,5 @@ Module for the articles that are part of the Spring REST E-book: 1. [Bootstrap a Web Application with Spring 5](https://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) 2. [Error Handling for REST with Spring](http://www.baeldung.com/exception-handling-for-rest-with-spring) -3. [REST Pagination in Spring](http://www.baeldung.com/rest-api-pagination-in-spring) \ No newline at end of file +3. [REST Pagination in Spring](http://www.baeldung.com/rest-api-pagination-in-spring) +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) diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index cf4ac0371b..3c8c4d7486 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -51,7 +51,6 @@ net.sourceforge.htmlunit htmlunit - ${htmlunit.version} test @@ -67,7 +66,6 @@ com.baeldung.SpringBootRestApplication - 2.32 27.0.1-jre diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java index d8996ca50d..1cc732ab08 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java @@ -1,16 +1,29 @@ package com.baeldung.persistence; import java.io.Serializable; +import java.util.List; import org.springframework.data.domain.Page; public interface IOperations { + // read - one + + T findOne(final long id); + // read - all + List findAll(); + Page findPaginated(int page, int size); // write T create(final T entity); + + T update(final T entity); + + void delete(final T entity); + + void deleteById(final long entityId); } diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java index 871f768895..5900c443b8 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java @@ -1,6 +1,7 @@ package com.baeldung.persistence.service.common; import java.io.Serializable; +import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -8,23 +9,54 @@ import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.transaction.annotation.Transactional; import com.baeldung.persistence.IOperations; +import com.google.common.collect.Lists; @Transactional public abstract class AbstractService implements IOperations { + // read - one + + @Override + @Transactional(readOnly = true) + public T findOne(final long id) { + return getDao().findById(id) + .get(); + } + // read - all + @Override + @Transactional(readOnly = true) + public List findAll() { + return Lists.newArrayList(getDao().findAll()); + } + @Override public Page findPaginated(final int page, final int size) { return getDao().findAll(PageRequest.of(page, size)); } // write - + @Override public T create(final T entity) { return getDao().save(entity); } + + @Override + public T update(final T entity) { + return getDao().save(entity); + } + + @Override + public void delete(final T entity) { + getDao().delete(entity); + } + + @Override + public void deleteById(final long entityId) { + getDao().deleteById(entityId); + } protected abstract PagingAndSortingRepository getDao(); diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java index 9d705f51d3..299e5ec214 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java @@ -1,5 +1,7 @@ package com.baeldung.persistence.service.impl; +import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -11,6 +13,7 @@ import com.baeldung.persistence.dao.IFooDao; import com.baeldung.persistence.model.Foo; import com.baeldung.persistence.service.IFooService; import com.baeldung.persistence.service.common.AbstractService; +import com.google.common.collect.Lists; @Service @Transactional @@ -36,5 +39,13 @@ public class FooService extends AbstractService implements IFooService { public Page findPaginated(Pageable pageable) { return dao.findAll(pageable); } + + // overridden to be secured + + @Override + @Transactional(readOnly = true) + public List findAll() { + return Lists.newArrayList(getDao().findAll()); + } } diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java index b35295cf99..59e33263db 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java @@ -9,14 +9,16 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.util.UriComponentsBuilder; import com.baeldung.persistence.model.Foo; @@ -24,9 +26,11 @@ import com.baeldung.persistence.service.IFooService; import com.baeldung.web.exception.MyResourceNotFoundException; import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent; import com.baeldung.web.hateoas.event.ResourceCreatedEvent; +import com.baeldung.web.hateoas.event.SingleResourceRetrievedEvent; +import com.baeldung.web.util.RestPreconditions; import com.google.common.base.Preconditions; -@Controller +@RestController @RequestMapping(value = "/auth/foos") public class FooController { @@ -42,10 +46,24 @@ public class FooController { // API + // read - one + + @GetMapping(value = "/{id}") + public Foo findById(@PathVariable("id") final Long id, final HttpServletResponse response) { + final Foo resourceById = RestPreconditions.checkFound(service.findOne(id)); + + eventPublisher.publishEvent(new SingleResourceRetrievedEvent(this, response)); + return resourceById; + } + // read - all - @RequestMapping(params = { "page", "size" }, method = RequestMethod.GET) - @ResponseBody + @GetMapping + public List findAll() { + return service.findAll(); + } + + @GetMapping(params = { "page", "size" }) public List findPaginated(@RequestParam("page") final int page, @RequestParam("size") final int size, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) { final Page resultPage = service.findPaginated(page, size); @@ -59,7 +77,6 @@ public class FooController { } @GetMapping("/pageable") - @ResponseBody public List findPaginatedWithPageable(Pageable pageable, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) { final Page resultPage = service.findPaginated(pageable); @@ -74,9 +91,8 @@ public class FooController { // write - @RequestMapping(method = RequestMethod.POST) + @PostMapping @ResponseStatus(HttpStatus.CREATED) - @ResponseBody public Foo create(@RequestBody final Foo resource, final HttpServletResponse response) { Preconditions.checkNotNull(resource); final Foo foo = service.create(resource); @@ -86,4 +102,18 @@ public class FooController { return foo; } + + @PutMapping(value = "/{id}") + @ResponseStatus(HttpStatus.OK) + public void update(@PathVariable("id") final Long id, @RequestBody final Foo resource) { + Preconditions.checkNotNull(resource); + RestPreconditions.checkFound(service.findOne(resource.getId())); + service.update(resource); + } + + @DeleteMapping(value = "/{id}") + @ResponseStatus(HttpStatus.OK) + public void delete(@PathVariable("id") final Long id) { + service.deleteById(id); + } } diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/SingleResourceRetrievedEvent.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/SingleResourceRetrievedEvent.java new file mode 100644 index 0000000000..70face083c --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/SingleResourceRetrievedEvent.java @@ -0,0 +1,22 @@ +package com.baeldung.web.hateoas.event; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.context.ApplicationEvent; + +public class SingleResourceRetrievedEvent extends ApplicationEvent { + private final HttpServletResponse response; + + public SingleResourceRetrievedEvent(final Object source, final HttpServletResponse response) { + super(source); + + this.response = response; + } + + // API + + public HttpServletResponse getResponse() { + return response; + } + +} \ No newline at end of file diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/SingleResourceRetrievedDiscoverabilityListener.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/SingleResourceRetrievedDiscoverabilityListener.java new file mode 100644 index 0000000000..d527c308b9 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/SingleResourceRetrievedDiscoverabilityListener.java @@ -0,0 +1,34 @@ +package com.baeldung.web.hateoas.listener; + +import javax.servlet.http.HttpServletResponse; + +import com.baeldung.web.hateoas.event.SingleResourceRetrievedEvent; +import com.baeldung.web.util.LinkUtil; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import com.google.common.base.Preconditions; +import com.google.common.net.HttpHeaders; + +@Component +class SingleResourceRetrievedDiscoverabilityListener implements ApplicationListener { + + @Override + public void onApplicationEvent(final SingleResourceRetrievedEvent resourceRetrievedEvent) { + Preconditions.checkNotNull(resourceRetrievedEvent); + + final HttpServletResponse response = resourceRetrievedEvent.getResponse(); + addLinkHeaderOnSingleResourceRetrieval(response); + } + + void addLinkHeaderOnSingleResourceRetrieval(final HttpServletResponse response) { + final String requestURL = ServletUriComponentsBuilder.fromCurrentRequestUri().build().toUri().toASCIIString(); + final int positionOfLastSlash = requestURL.lastIndexOf("/"); + final String uriForResourceCreation = requestURL.substring(0, positionOfLastSlash); + + final String linkHeaderValue = LinkUtil.createLinkHeader(uriForResourceCreation, "collection"); + response.addHeader(HttpHeaders.LINK, linkHeaderValue); + } + +} \ No newline at end of file diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java new file mode 100644 index 0000000000..bd5b5eb58e --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java @@ -0,0 +1,36 @@ +package com.baeldung.web; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; + +/** + * + * We'll start the whole context, but not the server. We'll mock the REST calls instead. + * + */ +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +public class FooControllerAppIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenFindPaginatedRequest_thenEmptyResponse() throws Exception { + this.mockMvc.perform(get("/auth/foos").param("page", "0") + .param("size", "2")) + .andExpect(status().isOk()) + .andExpect(content().json("[]")); + } + +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java new file mode 100644 index 0000000000..7e41cf6393 --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java @@ -0,0 +1,60 @@ +package com.baeldung.web; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.Collections; + +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.service.IFooService; +import com.baeldung.web.controller.FooController; +import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent; + +/** + * + * We'll start only the web layer. + * + */ +@RunWith(SpringRunner.class) +@WebMvcTest(FooController.class) +public class FooControllerWebLayerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private IFooService service; + + @MockBean + private ApplicationEventPublisher publisher; + + @Test() + public void givenPresentFoo_whenFindPaginatedRequest_thenPageWithFooRetrieved() throws Exception { + Page page = new PageImpl<>(Collections.singletonList(new Foo("fooName"))); + when(service.findPaginated(0, 2)).thenReturn(page); + doNothing().when(publisher) + .publishEvent(any(PaginatedResultsRetrievedEvent.class)); + + this.mockMvc.perform(get("/auth/foos").param("page", "0") + .param("size", "2")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$",Matchers.hasSize(1))); + } + +} diff --git a/spring-boot/README.MD b/spring-boot/README.MD index 2a6a935cc1..28123687fd 100644 --- a/spring-boot/README.MD +++ b/spring-boot/README.MD @@ -35,3 +35,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Load Spring Boot Properties From a JSON File](https://www.baeldung.com/spring-boot-json-properties) - [Display Auto-Configuration Report in Spring Boot](https://www.baeldung.com/spring-boot-auto-configuration-report) - [Injecting Git Information Into Spring](https://www.baeldung.com/spring-git-information) +- [Validation in Spring Boot](https://www.baeldung.com/spring-boot-bean-validation) diff --git a/spring-core/README.md b/spring-core/README.md index e5c359c11b..dcc15a4cb9 100644 --- a/spring-core/README.md +++ b/spring-core/README.md @@ -22,3 +22,4 @@ - [Spring Application Context Events](https://www.baeldung.com/spring-context-events) - [Unsatisfied Dependency in Spring](https://www.baeldung.com/spring-unsatisfied-dependency) - [What is a Spring Bean?](https://www.baeldung.com/spring-bean) +- [Spring PostConstruct and PreDestroy Annotations](https://www.baeldung.com/spring-postconstruct-predestroy) diff --git a/spring-core/src/main/java/com/baeldung/di/spring/Account.java b/spring-core/src/main/java/com/baeldung/di/spring/Account.java new file mode 100644 index 0000000000..6d9883bda5 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/Account.java @@ -0,0 +1,27 @@ +package com.baeldung.di.spring; + +import org.springframework.stereotype.Component; + +@Component +public class Account { + + private String accountNumber; + private String type; + + public String getAccountNumber() { + return accountNumber; + } + + public void setAccountNumber(String accountNumber) { + this.accountNumber = accountNumber; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/AccountService.java b/spring-core/src/main/java/com/baeldung/di/spring/AccountService.java new file mode 100644 index 0000000000..75ba6bb3eb --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/AccountService.java @@ -0,0 +1,5 @@ +package com.baeldung.di.spring; + +public interface AccountService { + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/AccountServiceImpl.java b/spring-core/src/main/java/com/baeldung/di/spring/AccountServiceImpl.java new file mode 100644 index 0000000000..4a4baf7d92 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/AccountServiceImpl.java @@ -0,0 +1,8 @@ +package com.baeldung.di.spring; + +import org.springframework.stereotype.Component; + +@Component +public class AccountServiceImpl implements AccountService { + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/AudioBookService.java b/spring-core/src/main/java/com/baeldung/di/spring/AudioBookService.java new file mode 100644 index 0000000000..c82e5ed282 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/AudioBookService.java @@ -0,0 +1,5 @@ +package com.baeldung.di.spring; + +public interface AudioBookService { + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/AudioBookServiceImpl.java b/spring-core/src/main/java/com/baeldung/di/spring/AudioBookServiceImpl.java new file mode 100644 index 0000000000..53a544b65a --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/AudioBookServiceImpl.java @@ -0,0 +1,5 @@ +package com.baeldung.di.spring; + +public class AudioBookServiceImpl implements AudioBookService { + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/AuthorService.java b/spring-core/src/main/java/com/baeldung/di/spring/AuthorService.java new file mode 100644 index 0000000000..cfb525ddf9 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/AuthorService.java @@ -0,0 +1,5 @@ +package com.baeldung.di.spring; + +public interface AuthorService { + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/AuthorServiceImpl.java b/spring-core/src/main/java/com/baeldung/di/spring/AuthorServiceImpl.java new file mode 100644 index 0000000000..007eb29930 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/AuthorServiceImpl.java @@ -0,0 +1,5 @@ +package com.baeldung.di.spring; + +public class AuthorServiceImpl implements AuthorService { + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/BookService.java b/spring-core/src/main/java/com/baeldung/di/spring/BookService.java new file mode 100644 index 0000000000..8e693e687d --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/BookService.java @@ -0,0 +1,5 @@ +package com.baeldung.di.spring; + +public interface BookService { + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/BookServiceImpl.java b/spring-core/src/main/java/com/baeldung/di/spring/BookServiceImpl.java new file mode 100644 index 0000000000..b4ea602234 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/BookServiceImpl.java @@ -0,0 +1,10 @@ +package com.baeldung.di.spring; + +import org.springframework.beans.factory.annotation.Autowired; + +public class BookServiceImpl implements BookService { + + @Autowired(required = false) + private AuthorService authorService; + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/Foo.java b/spring-core/src/main/java/com/baeldung/di/spring/Foo.java new file mode 100644 index 0000000000..9d9b5d0888 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/Foo.java @@ -0,0 +1,4 @@ +package com.baeldung.di.spring; + +public class Foo { +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/FooProcessor.java b/spring-core/src/main/java/com/baeldung/di/spring/FooProcessor.java new file mode 100644 index 0000000000..9baaaef7a3 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/FooProcessor.java @@ -0,0 +1,6 @@ +package com.baeldung.di.spring; + +public class FooProcessor { + + private Foo foo; +} \ No newline at end of file diff --git a/spring-core/src/main/java/com/baeldung/di/spring/PersonDao.java b/spring-core/src/main/java/com/baeldung/di/spring/PersonDao.java new file mode 100644 index 0000000000..8dde7ed1e0 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/PersonDao.java @@ -0,0 +1,5 @@ +package com.baeldung.di.spring; + +public interface PersonDao { + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/PersonDaoImpl.java b/spring-core/src/main/java/com/baeldung/di/spring/PersonDaoImpl.java new file mode 100644 index 0000000000..efcc2e0f21 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/PersonDaoImpl.java @@ -0,0 +1,8 @@ +package com.baeldung.di.spring; + +import org.springframework.stereotype.Component; + +@Component +public class PersonDaoImpl implements PersonDao { + +} \ No newline at end of file diff --git a/spring-core/src/main/java/com/baeldung/di/spring/SpringBeansConfig.java b/spring-core/src/main/java/com/baeldung/di/spring/SpringBeansConfig.java new file mode 100644 index 0000000000..4cb6943fc9 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/SpringBeansConfig.java @@ -0,0 +1,14 @@ +package com.baeldung.di.spring; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SpringBeansConfig { + + @Bean + public AudioBookService audioBookServiceGenerator() { + return new AudioBookServiceImpl(); + } + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/SpringMainConfig.java b/spring-core/src/main/java/com/baeldung/di/spring/SpringMainConfig.java new file mode 100644 index 0000000000..75066fd539 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/SpringMainConfig.java @@ -0,0 +1,18 @@ +package com.baeldung.di.spring; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import({ SpringBeansConfig.class }) +@ComponentScan("com.baeldung.di.spring") +public class SpringMainConfig { + + @Bean + public BookService bookServiceGenerator() { + return new BookServiceImpl(); + } + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/SpringPersonService.java b/spring-core/src/main/java/com/baeldung/di/spring/SpringPersonService.java new file mode 100644 index 0000000000..b85c749982 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/SpringPersonService.java @@ -0,0 +1,20 @@ +package com.baeldung.di.spring; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SpringPersonService { + + @Autowired + private PersonDao personDao; + + public PersonDao getPersonDao() { + return personDao; + } + + public void setPersonDao(PersonDao personDao) { + this.personDao = personDao; + } + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/UserService.java b/spring-core/src/main/java/com/baeldung/di/spring/UserService.java new file mode 100644 index 0000000000..330d7f7448 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/UserService.java @@ -0,0 +1,20 @@ +package com.baeldung.di.spring; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class UserService { + + @Autowired + private AccountService accountService; + + public AccountService getAccountService() { + return accountService; + } + + public void setAccountService(AccountService accountService) { + this.accountService = accountService; + } + +} diff --git a/spring-core/src/test/java/com/baeldung/di/spring/SpringUnitTest.java b/spring-core/src/test/java/com/baeldung/di/spring/SpringUnitTest.java new file mode 100644 index 0000000000..7df8dfac89 --- /dev/null +++ b/spring-core/src/test/java/com/baeldung/di/spring/SpringUnitTest.java @@ -0,0 +1,57 @@ +package com.baeldung.di.spring; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = { SpringMainConfig.class }) +public class SpringUnitTest { + @Autowired + ApplicationContext context; + + @Test + public void givenAccountServiceAutowiredToUserService_WhenGetAccountServiceInvoked_ThenReturnValueIsNotNull() { + UserService userService = context.getBean(UserService.class); + assertNotNull(userService.getAccountService()); + } + + @Test + public void givenBookServiceIsRegisteredAsBeanInContext_WhenBookServiceIsRetrievedFromContext_ThenReturnValueIsNotNull() { + BookService bookService = context.getBean(BookService.class); + assertNotNull(bookService); + } + + @Test + public void givenBookServiceIsRegisteredAsBeanInContextByOverridingAudioBookService_WhenAudioBookServiceIsRetrievedFromContext_ThenNoSuchBeanDefinitionExceptionIsThrown() { + BookService bookService = context.getBean(BookService.class); + assertNotNull(bookService); + AudioBookService audioBookService = context.getBean(AudioBookService.class); + assertNotNull(audioBookService); + } + + @Test + public void givenAuthorServiceAutowiredToBookServiceAsOptionalDependency_WhenBookServiceIsRetrievedFromContext_ThenNoSuchBeanDefinitionExceptionIsNotThrown() { + BookService bookService = context.getBean(BookService.class); + assertNotNull(bookService); + } + + @Test + public void givenSpringPersonServiceConstructorAnnotatedByAutowired_WhenSpringPersonServiceIsRetrievedFromContext_ThenInstanceWillBeCreatedFromTheConstructor() { + SpringPersonService personService = context.getBean(SpringPersonService.class); + assertNotNull(personService); + } + + @Test + public void givenPersonDaoAutowiredToSpringPersonServiceBySetterInjection_WhenSpringPersonServiceRetrievedFromContext_ThenPersonDaoInitializedByTheSetter() { + SpringPersonService personService = context.getBean(SpringPersonService.class); + assertNotNull(personService); + assertNotNull(personService.getPersonDao()); + } + +} diff --git a/spring-data-rest/src/test/java/com/baeldung/validator/SpringDataRestValidatorIntegrationTest.java b/spring-data-rest/src/test/java/com/baeldung/validator/SpringDataRestValidatorIntegrationTest.java index d41736e434..6da76d6a33 100644 --- a/spring-data-rest/src/test/java/com/baeldung/validator/SpringDataRestValidatorIntegrationTest.java +++ b/spring-data-rest/src/test/java/com/baeldung/validator/SpringDataRestValidatorIntegrationTest.java @@ -1,8 +1,12 @@ package com.baeldung.validator; -import com.baeldung.SpringDataRestApplication; -import com.baeldung.models.WebsiteUser; -import com.fasterxml.jackson.databind.ObjectMapper; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -10,14 +14,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.context.WebApplicationContext; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; +import com.baeldung.SpringDataRestApplication; +import com.baeldung.models.WebsiteUser; +import com.fasterxml.jackson.databind.ObjectMapper; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = SpringDataRestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @@ -42,6 +46,7 @@ public class SpringDataRestValidatorIntegrationTest { }; @Test + @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) public void whenAddingNewCorrectUser_thenCorrectStatusCodeAndResponse() throws Exception { WebsiteUser user = new WebsiteUser(); user.setEmail("john.doe@john.com"); @@ -83,6 +88,7 @@ public class SpringDataRestValidatorIntegrationTest { } @Test + @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) public void whenDeletingCorrectUser_thenCorrectStatusCodeAndResponse() throws Exception { WebsiteUser user = new WebsiteUser(); user.setEmail("john.doe@john.com"); @@ -92,6 +98,7 @@ public class SpringDataRestValidatorIntegrationTest { } @Test + @DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD) public void whenSearchingByEmail_thenCorrectStatusCodeAndResponse() throws Exception { WebsiteUser user = new WebsiteUser(); user.setEmail("john.doe@john.com"); diff --git a/spring-exceptions/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-exceptions/src/test/java/org/baeldung/SpringContextLiveTest.java similarity index 63% rename from spring-exceptions/src/test/java/org/baeldung/SpringContextIntegrationTest.java rename to spring-exceptions/src/test/java/org/baeldung/SpringContextLiveTest.java index 492673b168..ece7e0e730 100644 --- a/spring-exceptions/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/spring-exceptions/src/test/java/org/baeldung/SpringContextLiveTest.java @@ -1,16 +1,15 @@ package org.baeldung; -import org.baeldung.spring.config.CoreConfig; -import org.baeldung.spring.config.MvcConfig; import org.baeldung.spring.config.PersistenceConfig; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { CoreConfig.class, MvcConfig.class, PersistenceConfig.class}) -public class SpringContextIntegrationTest { +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class SpringContextLiveTest { @Test public void whenSpringContextIsBootstrapped_thenNoExceptions() { diff --git a/spring-mvc-java/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/spring-mvc-java/src/test/java/com/baeldung/SpringContextIntegrationTest.java new file mode 100644 index 0000000000..4c06917325 --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -0,0 +1,21 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.test.context.web.WebAppConfiguration; + +import com.baeldung.config.AppInitializer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { AppInitializer.class }, loader = AnnotationConfigContextLoader.class) +@WebAppConfiguration +public class SpringContextIntegrationTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + + } +} diff --git a/spring-mvc-simple/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/spring-mvc-simple/src/test/java/com/baeldung/SpringContextIntegrationTest.java new file mode 100644 index 0000000000..994c4865f7 --- /dev/null +++ b/spring-mvc-simple/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -0,0 +1,21 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import com.baeldung.spring.configuration.ApplicationConfiguration; + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes={ApplicationConfiguration.class}) +@WebAppConfiguration +public class SpringContextIntegrationTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} + diff --git a/spring-rest-full/.attach_pid28499 b/spring-rest-full/.attach_pid28499 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md index 2ef3a09e37..5140c4b270 100644 --- a/spring-rest-full/README.md +++ b/spring-rest-full/README.md @@ -16,7 +16,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Project Configuration with Spring](http://www.baeldung.com/project-configuration-with-spring) - [Metrics for your Spring REST API](http://www.baeldung.com/spring-rest-api-metrics) - [Bootstrap a Web Application with Spring 4](http://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) -- [Build a REST API with Spring and Java Config](http://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration) - [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic) diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java b/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java index 8c5593c3e8..0b617bf7ab 100644 --- a/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java +++ b/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java @@ -16,11 +16,7 @@ public interface IOperations { // write T create(final T entity); - + T update(final T entity); - void delete(final T entity); - - void deleteById(final long entityId); - } diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java b/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java index 59ccea8b12..059516eeba 100644 --- a/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java +++ b/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java @@ -40,16 +40,6 @@ public abstract class AbstractService implements IOperat return getDao().save(entity); } - @Override - public void delete(final T entity) { - getDao().delete(entity); - } - - @Override - public void deleteById(final long entityId) { - getDao().delete(entityId); - } - protected abstract PagingAndSortingRepository getDao(); } diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java b/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java index d46f1bfe90..32fe1bd7e0 100644 --- a/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java +++ b/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java @@ -1,7 +1,5 @@ package org.baeldung.persistence.service.impl; -import java.util.List; - import org.baeldung.persistence.dao.IFooDao; import org.baeldung.persistence.model.Foo; import org.baeldung.persistence.service.IFooService; @@ -11,8 +9,6 @@ import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import com.google.common.collect.Lists; - @Service @Transactional public class FooService extends AbstractService implements IFooService { @@ -38,12 +34,4 @@ public class FooService extends AbstractService implements IFooService { return dao.retrieveByName(name); } - // overridden to be secured - - @Override - @Transactional(readOnly = true) - public List findAll() { - return Lists.newArrayList(getDao().findAll()); - } - } diff --git a/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java b/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java index 443d0908ee..2e4dbcacc9 100644 --- a/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java +++ b/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java @@ -80,20 +80,6 @@ public class FooController { return foo; } - @RequestMapping(value = "/{id}", method = RequestMethod.PUT) - @ResponseStatus(HttpStatus.OK) - public void update(@PathVariable("id") final Long id, @RequestBody final Foo resource) { - Preconditions.checkNotNull(resource); - RestPreconditions.checkFound(service.findOne(resource.getId())); - service.update(resource); - } - - @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) - @ResponseStatus(HttpStatus.OK) - public void delete(@PathVariable("id") final Long id) { - service.deleteById(id); - } - @RequestMapping(method = RequestMethod.HEAD) @ResponseStatus(HttpStatus.OK) public void head(final HttpServletResponse resp) { diff --git a/spring-security-mvc-jsonview/.gitignore b/spring-security-mvc-jsonview/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/spring-security-mvc-jsonview/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-security-mvc-jsonview/pom.xml b/spring-security-mvc-jsonview/pom.xml new file mode 100644 index 0000000000..7f1129128f --- /dev/null +++ b/spring-security-mvc-jsonview/pom.xml @@ -0,0 +1,222 @@ + + 4.0.0 + + com.baeldung + spring-security-mvc-jsonview + 0.1-SNAPSHOT + spring-security-mvc-jsonview + war + + + com.baeldung + parent-spring-5 + 0.0.1-SNAPSHOT + ../parent-spring-5 + + + + + + com.fasterxml.jackson.core + jackson-core + 2.9.7 + + + com.fasterxml.jackson.core + jackson-annotations + 2.9.7 + + + com.fasterxml.jackson.core + jackson-databind + 2.9.7 + + + + + + org.springframework.security + spring-security-web + ${org.springframework.security.version} + + + org.springframework.security + spring-security-config + ${org.springframework.security.version} + + + org.springframework.security + spring-security-taglibs + ${org.springframework.security.version} + + + + + + org.springframework + spring-core + ${spring.version} + + + commons-logging + commons-logging + + + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-jdbc + ${spring.version} + + + org.springframework + spring-beans + ${spring.version} + + + org.springframework + spring-aop + ${spring.version} + + + org.springframework + spring-tx + ${spring.version} + + + org.springframework + spring-expression + ${spring.version} + + + + org.springframework + spring-web + ${spring.version} + + + org.springframework + spring-webmvc + ${spring.version} + + + + + + javax.servlet + javax.servlet-api + ${javax.servlet.version} + provided + + + + javax.servlet + jstl + ${jstl.version} + runtime + + + + + + org.springframework + spring-test + ${spring.version} + test + + + org.springframework.security + spring-security-test + ${org.springframework.security.version} + test + + + com.jayway.jsonpath + json-path + 2.4.0 + test + + + + + + spring-security-mvc-jsonview + + + src/main/resources + true + + + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + + default-war + prepare-package + + false + + + + + + + org.codehaus.cargo + cargo-maven2-plugin + ${cargo-maven2-plugin.version} + + + + ${project.build.directory}/${project.name}.war + war + + / + + + + + 2400000 + tomcat8x + embedded + + + + + + + 8084 + + + + + + + + + + + + 5.0.5.RELEASE + + + 3.1.0 + 1.2 + + + 2.6 + 1.6.1 + + + + \ No newline at end of file diff --git a/spring-security-mvc-jsonview/src/main/java/com/baeldung/AppInitializer.java b/spring-security-mvc-jsonview/src/main/java/com/baeldung/AppInitializer.java new file mode 100644 index 0000000000..4f38d190eb --- /dev/null +++ b/spring-security-mvc-jsonview/src/main/java/com/baeldung/AppInitializer.java @@ -0,0 +1,33 @@ +package com.baeldung; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.filter.DelegatingFilterProxy; +import org.springframework.web.servlet.DispatcherServlet; + +public class AppInitializer implements WebApplicationInitializer { + + @Override + public void onStartup(final ServletContext sc) throws ServletException { + + AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); + + root.scan("com.baeldung"); + sc.addListener(new ContextLoaderListener(root)); + + ServletRegistration.Dynamic appServlet = sc.addServlet("mvc", new DispatcherServlet(new GenericWebApplicationContext())); + appServlet.setLoadOnStartup(1); + appServlet.addMapping("/"); + + sc.addFilter("securityFilter", new DelegatingFilterProxy("springSecurityFilterChain")) + .addMappingForUrlPatterns(null, false, "/*"); + + } + +} diff --git a/spring-security-mvc-jsonview/src/main/java/com/baeldung/controller/ItemsController.java b/spring-security-mvc-jsonview/src/main/java/com/baeldung/controller/ItemsController.java new file mode 100644 index 0000000000..16268a239b --- /dev/null +++ b/spring-security-mvc-jsonview/src/main/java/com/baeldung/controller/ItemsController.java @@ -0,0 +1,21 @@ +package com.baeldung.controller; + +import com.baeldung.model.Item; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; + +@RestController +public class ItemsController { + + @RequestMapping("/items") + public Collection getItems() { + return Arrays.asList(new Item(1, "Item 1", "Frank"), new Item(2, "Item 2", "Bob")); + } + +} diff --git a/spring-security-mvc-jsonview/src/main/java/com/baeldung/controller/View.java b/spring-security-mvc-jsonview/src/main/java/com/baeldung/controller/View.java new file mode 100644 index 0000000000..10ae50adef --- /dev/null +++ b/spring-security-mvc-jsonview/src/main/java/com/baeldung/controller/View.java @@ -0,0 +1,24 @@ +package com.baeldung.controller; + +import com.baeldung.spring.AppConfig.Role; + +import java.util.HashMap; +import java.util.Map; + +public class View { + + public static final Map MAPPING = new HashMap<>(); + + static { + MAPPING.put(Role.ROLE_ADMIN, Admin.class); + MAPPING.put(Role.ROLE_USER, User.class); + } + + public static class User { + + } + + public static class Admin extends User { + + } +} diff --git a/spring-security-mvc-jsonview/src/main/java/com/baeldung/model/Item.java b/spring-security-mvc-jsonview/src/main/java/com/baeldung/model/Item.java new file mode 100644 index 0000000000..002ee73e4f --- /dev/null +++ b/spring-security-mvc-jsonview/src/main/java/com/baeldung/model/Item.java @@ -0,0 +1,32 @@ +package com.baeldung.model; + +import com.baeldung.controller.View; +import com.fasterxml.jackson.annotation.JsonView; + +public class Item { + + @JsonView(View.User.class) + private int id; + @JsonView(View.User.class) + private String name; + @JsonView(View.Admin.class) + private String ownerName; + + public Item(int id, String name, String ownerName) { + this.id = id; + this.name = name; + this.ownerName = ownerName; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public String getOwnerName() { + return ownerName; + } +} diff --git a/spring-security-mvc-jsonview/src/main/java/com/baeldung/spring/AppConfig.java b/spring-security-mvc-jsonview/src/main/java/com/baeldung/spring/AppConfig.java new file mode 100644 index 0000000000..10b2d2447e --- /dev/null +++ b/spring-security-mvc-jsonview/src/main/java/com/baeldung/spring/AppConfig.java @@ -0,0 +1,51 @@ +package com.baeldung.spring; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.Arrays; + +@Configuration +@EnableWebMvc +@EnableWebSecurity +@ComponentScan("com.baeldung") +public class AppConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer { + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("user").password(passwordEncoder().encode("userPass")).roles("USER") + .and() + .withUser("admin").password(passwordEncoder().encode("adminPass")).roles("ADMIN"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + http + .csrf().disable() + .authorizeRequests() + .anyRequest().authenticated() + .and().httpBasic(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + + + public enum Role { + ROLE_USER, + ROLE_ADMIN + } +} diff --git a/spring-security-mvc-jsonview/src/main/java/com/baeldung/spring/SecurityJsonViewControllerAdvice.java b/spring-security-mvc-jsonview/src/main/java/com/baeldung/spring/SecurityJsonViewControllerAdvice.java new file mode 100644 index 0000000000..d6d022a110 --- /dev/null +++ b/spring-security-mvc-jsonview/src/main/java/com/baeldung/spring/SecurityJsonViewControllerAdvice.java @@ -0,0 +1,39 @@ +package com.baeldung.spring; + +import com.baeldung.controller.View; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.MappingJacksonValue; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.AbstractMappingJacksonResponseBodyAdvice; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +@RestControllerAdvice +public class SecurityJsonViewControllerAdvice extends AbstractMappingJacksonResponseBodyAdvice { + + @Override + protected void beforeBodyWriteInternal(MappingJacksonValue bodyContainer, MediaType contentType, + MethodParameter returnType, ServerHttpRequest request, ServerHttpResponse response) { + if (SecurityContextHolder.getContext().getAuthentication() != null + && SecurityContextHolder.getContext().getAuthentication().getAuthorities() != null) { + Collection authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities(); + List jsonViews = authorities.stream() + .map(GrantedAuthority::getAuthority) + .map(AppConfig.Role::valueOf) + .map(View.MAPPING::get) + .collect(Collectors.toList()); + if (jsonViews.size() == 1) { + bodyContainer.setSerializationView(jsonViews.get(0)); + return; + } + throw new IllegalArgumentException("Ambiguous @JsonView declaration for roles "+ authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(","))); + } + } +} diff --git a/spring-security-mvc-jsonview/src/main/resources/logback.xml b/spring-security-mvc-jsonview/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/spring-security-mvc-jsonview/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-security-mvc-jsonview/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/spring-security-mvc-jsonview/src/test/java/com/baeldung/SpringContextIntegrationTest.java new file mode 100644 index 0000000000..e22cd3d71a --- /dev/null +++ b/spring-security-mvc-jsonview/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -0,0 +1,17 @@ +package com.baeldung; + +import com.baeldung.spring.AppConfig; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = AppConfig.class) +@WebAppConfiguration +public class SpringContextIntegrationTest { + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-security-mvc-jsonview/src/test/java/com/baeldung/security/SpringSecurityJsonViewIntegrationTest.java b/spring-security-mvc-jsonview/src/test/java/com/baeldung/security/SpringSecurityJsonViewIntegrationTest.java new file mode 100644 index 0000000000..626c8cb497 --- /dev/null +++ b/spring-security-mvc-jsonview/src/test/java/com/baeldung/security/SpringSecurityJsonViewIntegrationTest.java @@ -0,0 +1,85 @@ +package com.baeldung.security; + +import com.baeldung.spring.AppConfig; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.test.context.support.WithMockUser; +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 org.springframework.web.util.NestedServletException; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = AppConfig.class) +@WebAppConfiguration +public class SpringSecurityJsonViewIntegrationTest { + + @Autowired + private WebApplicationContext context; + + private MockMvc mvc; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Before + public void setup() { + mvc = MockMvcBuilders + .webAppContextSetup(context) + .build(); + } + + @Test + @WithMockUser(username = "admin", password = "adminPass", roles = "ADMIN") + public void whenAdminRequests_thenOwnerNameIsPresent() throws Exception { + mvc.perform(get("/items")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id").value(1)) + .andExpect(jsonPath("$[0].name").value("Item 1")) + .andExpect(jsonPath("$[0].ownerName").exists()); + } + + @Test + @WithMockUser(username = "user", password = "userPass", roles = "USER") + public void whenUserRequests_thenOwnerNameIsAbsent() throws Exception { + mvc.perform(get("/items")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id").value(1)) + .andExpect(jsonPath("$[0].name").value("Item 1")) + .andExpect(jsonPath("$[0].ownerName").doesNotExist()); + } + + @Test + @WithMockUser(username = "user", password = "userPass", roles = {"ADMIN", "USER"}) + public void whenMultipleRoles_thenExceptionIsThrown() throws Exception { + expectedException.expect(new BaseMatcher() { + @Override + public boolean matches(Object o) { + NestedServletException exception = (NestedServletException) o; + return exception.getCause() instanceof IllegalArgumentException && exception.getCause().getMessage().equals("Ambiguous @JsonView declaration for roles ROLE_ADMIN,ROLE_USER"); + } + + @Override + public void describeTo(Description description) { + + } + }); + + mvc.perform(get("/items")) + .andExpect(status().isOk()); + + } +} diff --git a/spring-security-x509/keystore/Makefile b/spring-security-x509/keystore/Makefile index 2b5b5e8abe..2cd7c55c5b 100644 --- a/spring-security-x509/keystore/Makefile +++ b/spring-security-x509/keystore/Makefile @@ -2,6 +2,7 @@ PASSWORD=changeit KEYSTORE=keystore.jks HOSTNAME=localhost CLIENTNAME=cid +CLIENT_PRIVATE_KEY="${CLIENTNAME}_pk" # CN = Common Name # OU = Organization Unit @@ -59,12 +60,12 @@ create-truststore: export-authority add-client: # Generate client certificate - keytool -genkey -alias $(CLIENTNAME) -ext san=dns:localhost,ip:127.0.0.1 \ + keytool -genkey -alias $(CLIENT_PRIVATE_KEY) -ext san=dns:localhost,ip:127.0.0.1 \ -keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \ -validity 3650 -dname $(DNAME_CLIENT) \ -keystore $(TRUSTSTORE) -storepass $(PASSWORD) # Generate a host certificate signing request - keytool -certreq -alias $(CLIENTNAME) -ext san=dns:localhost,ip:127.0.0.1 -ext BC=ca:true \ + keytool -certreq -alias $(CLIENT_PRIVATE_KEY) -ext san=dns:localhost,ip:127.0.0.1 -ext BC=ca:true \ -keyalg RSA -keysize 4096 -sigalg SHA512withRSA \ -validity 3650 -file "$(CLIENTNAME).csr" \ -keystore $(TRUSTSTORE) -storepass $(PASSWORD) @@ -78,10 +79,13 @@ add-client: -file "$(CLIENTNAME).crt" \ -keystore $(TRUSTSTORE) -storepass $(PASSWORD) # Export private certificate for importing into a browser - keytool -importkeystore -srcalias $(CLIENTNAME) -ext san=dns:localhost,ip:127.0.0.1 \ + keytool -importkeystore -srcalias $(CLIENT_PRIVATE_KEY) -ext san=dns:localhost,ip:127.0.0.1 \ -srckeystore $(TRUSTSTORE) -srcstorepass $(PASSWORD) \ -destkeystore "$(CLIENTNAME).p12" -deststorepass $(PASSWORD) \ -deststoretype PKCS12 + # Delete client private key as truststore should not contain any private keys + keytool -delete -alias $(CLIENT_PRIVATE_KEY) \ + -keystore $(TRUSTSTORE) -storepass $(PASSWORD) clean: # Remove generated artifacts diff --git a/spring-static-resources/pom.xml b/spring-static-resources/pom.xml index 3ca7783682..92f6616839 100644 --- a/spring-static-resources/pom.xml +++ b/spring-static-resources/pom.xml @@ -140,6 +140,14 @@ handlebars ${handlebars.version} + + + org.springframework + spring-test + ${spring.version} + test + + diff --git a/spring-static-resources/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/spring-static-resources/src/test/java/com/baeldung/SpringContextIntegrationTest.java new file mode 100644 index 0000000000..67dc50030c --- /dev/null +++ b/spring-static-resources/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -0,0 +1,20 @@ +package com.baeldung; + +import org.baeldung.spring.SecSecurityConfig; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { SecSecurityConfig.class }, loader = AnnotationConfigContextLoader.class) +@WebAppConfiguration +public class SpringContextIntegrationTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + + } +} diff --git a/testing-modules/junit-5/README.md b/testing-modules/junit-5/README.md index 1fbd7a4a5e..4ed01e7fa9 100644 --- a/testing-modules/junit-5/README.md +++ b/testing-modules/junit-5/README.md @@ -16,3 +16,4 @@ - [Running JUnit Tests Programmatically, from a Java Application](https://www.baeldung.com/junit-tests-run-programmatically-from-java) - [Testing an Abstract Class With JUnit](https://www.baeldung.com/junit-test-abstract-class) - [A Quick JUnit vs TestNG Comparison](http://www.baeldung.com/junit-vs-testng) +- [Guide to JUnit 5 Parameterized Tests](https://www.baeldung.com/parameterized-tests-junit-5)