diff --git a/algorithms-miscellaneous-1/pom.xml b/algorithms-miscellaneous-1/pom.xml index fe670963c0..30130208f8 100644 --- a/algorithms-miscellaneous-1/pom.xml +++ b/algorithms-miscellaneous-1/pom.xml @@ -39,6 +39,11 @@ ${org.assertj.core.version} test + + com.github.dpaukov + combinatoricslib3 + 3.3.0 + @@ -77,7 +82,7 @@ 3.6.1 3.9.0 1.11 - 25.1-jre + 27.0.1-jre \ No newline at end of file diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java new file mode 100644 index 0000000000..40142ce940 --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java @@ -0,0 +1,29 @@ +package com.baeldung.algorithms.combination; + +import java.util.Arrays; +import java.util.Iterator; + +import org.apache.commons.math3.util.CombinatoricsUtils; + +public class ApacheCommonsCombinationGenerator { + + private static final int N = 6; + private static final int R = 3; + + /** + * Print all combinations of r elements from a set + * @param n - number of elements in set + * @param r - number of elements in selection + */ + public static void generate(int n, int r) { + Iterator iterator = CombinatoricsUtils.combinationsIterator(n, r); + while (iterator.hasNext()) { + final int[] combination = iterator.next(); + System.out.println(Arrays.toString(combination)); + } + } + + public static void main(String[] args) { + generate(N, R); + } +} \ No newline at end of file diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java new file mode 100644 index 0000000000..0afdeefb8b --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java @@ -0,0 +1,13 @@ +package com.baeldung.algorithms.combination; + +import org.paukov.combinatorics3.Generator; + +public class CombinatoricsLibCombinationGenerator { + + public static void main(String[] args) { + Generator.combination(0, 1, 2, 3, 4, 5) + .simple(3) + .stream() + .forEach(System.out::println); + } +} diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java new file mode 100644 index 0000000000..d2783881ba --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java @@ -0,0 +1,17 @@ +package com.baeldung.algorithms.combination; + +import java.util.Arrays; +import java.util.Set; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; + +public class GuavaCombinationsGenerator { + + public static void main(String[] args) { + + Set> combinations = Sets.combinations(ImmutableSet.of(0, 1, 2, 3, 4, 5), 3); + System.out.println(combinations.size()); + System.out.println(Arrays.toString(combinations.toArray())); + } +} diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java new file mode 100644 index 0000000000..676d2f41e3 --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java @@ -0,0 +1,52 @@ +package com.baeldung.algorithms.combination; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class IterativeCombinationGenerator { + + private static final int N = 5; + private static final int R = 2; + + /** + * Generate all combinations of r elements from a set + * @param n the number of elements in input set + * @param r the number of elements in a combination + * @return the list containing all combinations + */ + public List generate(int n, int r) { + List combinations = new ArrayList<>(); + int[] combination = new int[r]; + + // initialize with lowest lexicographic combination + for (int i = 0; i < r; i++) { + combination[i] = i; + } + + while (combination[r - 1] < n) { + combinations.add(combination.clone()); + + // generate next combination in lexicographic order + int t = r - 1; + while (t != 0 && combination[t] == n - r + t) { + t--; + } + combination[t]++; + for (int i = t + 1; i < r; i++) { + combination[i] = combination[i - 1] + 1; + } + } + + return combinations; + } + + public static void main(String[] args) { + IterativeCombinationGenerator generator = new IterativeCombinationGenerator(); + List combinations = generator.generate(N, R); + System.out.println(combinations.size()); + for (int[] combination : combinations) { + System.out.println(Arrays.toString(combination)); + } + } +} diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java new file mode 100644 index 0000000000..52305b8c2f --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java @@ -0,0 +1,53 @@ +package com.baeldung.algorithms.combination; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class SelectionRecursiveCombinationGenerator { + + private static final int N = 6; + private static final int R = 3; + + /** + * Generate all combinations of r elements from a set + * @param n - number of elements in input set + * @param r - number of elements to be chosen + * @return the list containing all combinations + */ + public List generate(int n, int r) { + List combinations = new ArrayList<>(); + helper(combinations, new int[r], 0, n - 1, 0); + return combinations; + } + + /** + * Choose elements from set by recursing over elements selected + * @param combinations - List to store generated combinations + * @param data - current combination + * @param start - starting element of remaining set + * @param end - last element of remaining set + * @param index - number of elements chosen so far. + */ + private void helper(List combinations, int data[], int start, int end, int index) { + if (index == data.length) { + int[] combination = data.clone(); + combinations.add(combination); + } else { + int max = Math.min(end, end + 1 - data.length + index); + for (int i = start; i <= max; i++) { + data[index] = i; + helper(combinations, data, i + 1, end, index + 1); + } + } + } + + public static void main(String[] args) { + SelectionRecursiveCombinationGenerator generator = new SelectionRecursiveCombinationGenerator(); + List combinations = generator.generate(N, R); + for (int[] combination : combinations) { + System.out.println(Arrays.toString(combination)); + } + System.out.printf("generated %d combinations of %d items from %d ", combinations.size(), R, N); + } +} diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java new file mode 100644 index 0000000000..a73447b31d --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java @@ -0,0 +1,50 @@ +package com.baeldung.algorithms.combination; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class SetRecursiveCombinationGenerator { + + private static final int N = 5; + private static final int R = 2; + + /** + * Generate all combinations of r elements from a set + * @param n - number of elements in set + * @param r - number of elements in selection + * @return the list containing all combinations + */ + public List generate(int n, int r) { + List combinations = new ArrayList<>(); + helper(combinations, new int[r], 0, n-1, 0); + return combinations; + } + + /** + * @param combinations - List to contain the generated combinations + * @param data - List of elements in the selection + * @param start - index of the starting element in the remaining set + * @param end - index of the last element in the set + * @param index - number of elements selected so far + */ + private void helper(List combinations, int data[], int start, int end, int index) { + if (index == data.length) { + int[] combination = data.clone(); + combinations.add(combination); + } else if (start <= end) { + data[index] = start; + helper(combinations, data, start + 1, end, index + 1); + helper(combinations, data, start + 1, end, index); + } + } + + public static void main(String[] args) { + SetRecursiveCombinationGenerator generator = new SetRecursiveCombinationGenerator(); + List combinations = generator.generate(N, R); + for (int[] combination : combinations) { + System.out.println(Arrays.toString(combination)); + } + System.out.printf("generated %d combinations of %d items from %d ", combinations.size(), R, N); + } +} diff --git a/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java b/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java new file mode 100644 index 0000000000..987b6ddae6 --- /dev/null +++ b/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java @@ -0,0 +1,35 @@ +package com.baeldung.algorithms.combination; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; + +import org.junit.Test; + +public class CombinationUnitTest { + + private static final int N = 5; + private static final int R = 3; + private static final int nCr = 10; + + @Test + public void givenSetAndSelectionSize_whenCalculatedUsingSetRecursiveAlgorithm_thenExpectedCount() { + SetRecursiveCombinationGenerator generator = new SetRecursiveCombinationGenerator(); + List selection = generator.generate(N, R); + assertEquals(nCr, selection.size()); + } + + @Test + public void givenSetAndSelectionSize_whenCalculatedUsingSelectionRecursiveAlgorithm_thenExpectedCount() { + SelectionRecursiveCombinationGenerator generator = new SelectionRecursiveCombinationGenerator(); + List selection = generator.generate(N, R); + assertEquals(nCr, selection.size()); + } + + @Test + public void givenSetAndSelectionSize_whenCalculatedUsingIterativeAlgorithm_thenExpectedCount() { + IterativeCombinationGenerator generator = new IterativeCombinationGenerator(); + List selection = generator.generate(N, R); + assertEquals(nCr, selection.size()); + } +} diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeNode.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeNode.java new file mode 100644 index 0000000000..7905b752a9 --- /dev/null +++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeNode.java @@ -0,0 +1,42 @@ +package com.baeldung.algorithms.reversingtree; + +public class TreeNode { + + private int value; + private TreeNode rightChild; + private TreeNode leftChild; + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + public TreeNode getRightChild() { + return rightChild; + } + + public void setRightChild(TreeNode rightChild) { + this.rightChild = rightChild; + } + + public TreeNode getLeftChild() { + return leftChild; + } + + public void setLeftChild(TreeNode leftChild) { + this.leftChild = leftChild; + } + + public TreeNode(int value, TreeNode rightChild, TreeNode leftChild) { + this.value = value; + this.rightChild = rightChild; + this.leftChild = leftChild; + } + + public TreeNode(int value) { + this.value = value; + } +} diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeReverser.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeReverser.java new file mode 100644 index 0000000000..6d3a9ddd31 --- /dev/null +++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeReverser.java @@ -0,0 +1,68 @@ +package com.baeldung.algorithms.reversingtree; + +import java.util.LinkedList; + +public class TreeReverser { + + public TreeNode createBinaryTree() { + + TreeNode leaf1 = new TreeNode(3); + TreeNode leaf2 = new TreeNode(1); + TreeNode leaf3 = new TreeNode(9); + TreeNode leaf4 = new TreeNode(6); + + TreeNode nodeLeft = new TreeNode(2, leaf1, leaf2); + TreeNode nodeRight = new TreeNode(7, leaf3, leaf4); + + TreeNode root = new TreeNode(4, nodeRight, nodeLeft); + + return root; + } + + public void reverseRecursive(TreeNode treeNode) { + if (treeNode == null) { + return; + } + + TreeNode temp = treeNode.getLeftChild(); + treeNode.setLeftChild(treeNode.getRightChild()); + treeNode.setRightChild(temp); + + reverseRecursive(treeNode.getLeftChild()); + reverseRecursive(treeNode.getRightChild()); + } + + public void reverseIterative(TreeNode treeNode) { + LinkedList queue = new LinkedList(); + + if (treeNode != null) { + queue.add(treeNode); + } + + while (!queue.isEmpty()) { + + TreeNode node = queue.poll(); + if (node.getLeftChild() != null) + queue.add(node.getLeftChild()); + if (node.getRightChild() != null) + queue.add(node.getRightChild()); + + TreeNode temp = node.getLeftChild(); + node.setLeftChild(node.getRightChild()); + node.setRightChild(temp); + } + } + + public String toString(TreeNode root) { + if (root == null) { + return ""; + } + + StringBuffer buffer = new StringBuffer(String.valueOf(root.getValue())).append(" "); + + buffer.append(toString(root.getLeftChild())); + buffer.append(toString(root.getRightChild())); + + return buffer.toString(); + } +} diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/reversingtree/TreeReverserUnitTest.java b/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/reversingtree/TreeReverserUnitTest.java new file mode 100644 index 0000000000..cbc265fae1 --- /dev/null +++ b/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/reversingtree/TreeReverserUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.algorithms.reversingtree; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class TreeReverserUnitTest { + + @Test + public void givenTreeWhenReversingRecursivelyThenReversed() { + TreeReverser reverser = new TreeReverser(); + + TreeNode treeNode = reverser.createBinaryTree(); + + reverser.reverseRecursive(treeNode); + + assertEquals("4 7 9 6 2 3 1", reverser.toString(treeNode) + .trim()); + } + + @Test + public void givenTreeWhenReversingIterativelyThenReversed() { + TreeReverser reverser = new TreeReverser(); + + TreeNode treeNode = reverser.createBinaryTree(); + + reverser.reverseIterative(treeNode); + + assertEquals("4 7 9 6 2 3 1", reverser.toString(treeNode) + .trim()); + } + +} diff --git a/aws/README.md b/aws/README.md index 2c61928095..d14ea8a75e 100644 --- a/aws/README.md +++ b/aws/README.md @@ -4,7 +4,6 @@ - [AWS S3 with Java](http://www.baeldung.com/aws-s3-java) - [AWS Lambda With Java](http://www.baeldung.com/java-aws-lambda) - [Managing EC2 Instances in Java](http://www.baeldung.com/ec2-java) -- [http://www.baeldung.com/aws-s3-multipart-upload](https://github.com/eugenp/tutorials/tree/master/aws) - [Multipart Uploads in Amazon S3 with Java](http://www.baeldung.com/aws-s3-multipart-upload) - [Integration Testing with a Local DynamoDB Instance](http://www.baeldung.com/dynamodb-local-integration-tests) - [Using the JetS3t Java Client With Amazon S3](http://www.baeldung.com/jets3t-amazon-s3) diff --git a/cas/pom.xml b/cas/pom.xml new file mode 100644 index 0000000000..6d141277c5 --- /dev/null +++ b/cas/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + cas + cas + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + cas-secured-app + cas-server + + + diff --git a/cloud-foundry-uaa/cf-uaa-config/uaa.yml b/cloud-foundry-uaa/cf-uaa-config/uaa.yml new file mode 100644 index 0000000000..b782c2b681 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-config/uaa.yml @@ -0,0 +1,73 @@ +issuer: + uri: http://localhost:8080/uaa + +spring_profiles: postgresql,default + +database.driverClassName: org.postgresql.Driver +database.url: jdbc:postgresql:uaadb2 +database.username: postgres +database.password: postgres + +encryption: + active_key_label: CHANGE-THIS-KEY + encryption_keys: + - label: CHANGE-THIS-KEY + passphrase: CHANGEME + +login: + serviceProviderKey: | + -----BEGIN RSA PRIVATE KEY----- + MIICXQIBAAKBgQDHtC5gUXxBKpEqZTLkNvFwNGnNIkggNOwOQVNbpO0WVHIivig5 + L39WqS9u0hnA+O7MCA/KlrAR4bXaeVVhwfUPYBKIpaaTWFQR5cTR1UFZJL/OF9vA + fpOwznoD66DDCnQVpbCjtDYWX+x6imxn8HCYxhMol6ZnTbSsFW6VZjFMjQIDAQAB + AoGAVOj2Yvuigi6wJD99AO2fgF64sYCm/BKkX3dFEw0vxTPIh58kiRP554Xt5ges + 7ZCqL9QpqrChUikO4kJ+nB8Uq2AvaZHbpCEUmbip06IlgdA440o0r0CPo1mgNxGu + lhiWRN43Lruzfh9qKPhleg2dvyFGQxy5Gk6KW/t8IS4x4r0CQQD/dceBA+Ndj3Xp + ubHfxqNz4GTOxndc/AXAowPGpge2zpgIc7f50t8OHhG6XhsfJ0wyQEEvodDhZPYX + kKBnXNHzAkEAyCA76vAwuxqAd3MObhiebniAU3SnPf2u4fdL1EOm92dyFs1JxyyL + gu/DsjPjx6tRtn4YAalxCzmAMXFSb1qHfwJBAM3qx3z0gGKbUEWtPHcP7BNsrnWK + vw6By7VC8bk/ffpaP2yYspS66Le9fzbFwoDzMVVUO/dELVZyBnhqSRHoXQcCQQCe + A2WL8S5o7Vn19rC0GVgu3ZJlUrwiZEVLQdlrticFPXaFrn3Md82ICww3jmURaKHS + N+l4lnMda79eSp3OMmq9AkA0p79BvYsLshUJJnvbk76pCjR28PK4dV1gSDUEqQMB + qy45ptdwJLqLJCeNoR0JUcDNIRhOCuOPND7pcMtX6hI/ + -----END RSA PRIVATE KEY----- + serviceProviderKeyPassword: password + serviceProviderCertificate: | + -----BEGIN CERTIFICATE----- + MIIDSTCCArKgAwIBAgIBADANBgkqhkiG9w0BAQQFADB8MQswCQYDVQQGEwJhdzEO + MAwGA1UECBMFYXJ1YmExDjAMBgNVBAoTBWFydWJhMQ4wDAYDVQQHEwVhcnViYTEO + MAwGA1UECxMFYXJ1YmExDjAMBgNVBAMTBWFydWJhMR0wGwYJKoZIhvcNAQkBFg5h + cnViYUBhcnViYS5hcjAeFw0xNTExMjAyMjI2MjdaFw0xNjExMTkyMjI2MjdaMHwx + CzAJBgNVBAYTAmF3MQ4wDAYDVQQIEwVhcnViYTEOMAwGA1UEChMFYXJ1YmExDjAM + BgNVBAcTBWFydWJhMQ4wDAYDVQQLEwVhcnViYTEOMAwGA1UEAxMFYXJ1YmExHTAb + BgkqhkiG9w0BCQEWDmFydWJhQGFydWJhLmFyMIGfMA0GCSqGSIb3DQEBAQUAA4GN + ADCBiQKBgQDHtC5gUXxBKpEqZTLkNvFwNGnNIkggNOwOQVNbpO0WVHIivig5L39W + qS9u0hnA+O7MCA/KlrAR4bXaeVVhwfUPYBKIpaaTWFQR5cTR1UFZJL/OF9vAfpOw + znoD66DDCnQVpbCjtDYWX+x6imxn8HCYxhMol6ZnTbSsFW6VZjFMjQIDAQABo4Ha + MIHXMB0GA1UdDgQWBBTx0lDzjH/iOBnOSQaSEWQLx1syGDCBpwYDVR0jBIGfMIGc + gBTx0lDzjH/iOBnOSQaSEWQLx1syGKGBgKR+MHwxCzAJBgNVBAYTAmF3MQ4wDAYD + VQQIEwVhcnViYTEOMAwGA1UEChMFYXJ1YmExDjAMBgNVBAcTBWFydWJhMQ4wDAYD + VQQLEwVhcnViYTEOMAwGA1UEAxMFYXJ1YmExHTAbBgkqhkiG9w0BCQEWDmFydWJh + QGFydWJhLmFyggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAYvBJ + 0HOZbbHClXmGUjGs+GS+xC1FO/am2suCSYqNB9dyMXfOWiJ1+TLJk+o/YZt8vuxC + KdcZYgl4l/L6PxJ982SRhc83ZW2dkAZI4M0/Ud3oePe84k8jm3A7EvH5wi5hvCkK + RpuRBwn3Ei+jCRouxTbzKPsuCVB+1sNyxMTXzf0= + -----END CERTIFICATE----- + +#The secret that an external login server will use to authenticate to the uaa using the id `login` +LOGIN_SECRET: loginsecret + +jwt: + token: + signing-key: | + -----BEGIN RSA PRIVATE KEY----- + MIIEpAIBAAKCAQEAqUeygEfDGxI6c1VDQ6xIyUSLrP6iz1y97iHFbtXSxXaArL4a + ... + v6Mtt5LcRAAVP7pemunTdju4h8Q/noKYlVDVL30uLYUfKBL4UKfOBw== + -----END RSA PRIVATE KEY----- + verification-key: | + -----BEGIN PUBLIC KEY----- + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqUeygEfDGxI6c1VDQ6xI + ... + AwIDAQAB + -----END PUBLIC KEY----- diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml b/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml new file mode 100644 index 0000000000..8e31cc41fb --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + com.example + cf-uaa-oauth2-client + 0.0.1-SNAPSHOT + uaa-client-webapp + Demo project for Spring Boot + + + 1.8 + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-oauth2-client + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientApplication.java b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientApplication.java new file mode 100644 index 0000000000..c9e81fcd5d --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.cfuaa.oauth2.client; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CFUAAOAuth2ClientApplication { + + public static void main(String[] args) { + SpringApplication.run(CFUAAOAuth2ClientApplication.class, args); + } + +} diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientController.java b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientController.java new file mode 100644 index 0000000000..b1631ed327 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientController.java @@ -0,0 +1,80 @@ +package com.baeldung.cfuaa.oauth2.client; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; + +@RestController +public class CFUAAOAuth2ClientController { + + @Value("${resource.server.url}") + private String remoteResourceServer; + + private RestTemplate restTemplate; + + private OAuth2AuthorizedClientService authorizedClientService; + + public CFUAAOAuth2ClientController(OAuth2AuthorizedClientService authorizedClientService) { + this.authorizedClientService = authorizedClientService; + this.restTemplate = new RestTemplate(); + } + + @RequestMapping("/") + public String index(OAuth2AuthenticationToken authenticationToken) { + OAuth2AuthorizedClient oAuth2AuthorizedClient = this.authorizedClientService.loadAuthorizedClient(authenticationToken.getAuthorizedClientRegistrationId(), authenticationToken.getName()); + OAuth2AccessToken oAuth2AccessToken = oAuth2AuthorizedClient.getAccessToken(); + + String response = "Hello, " + authenticationToken.getPrincipal().getName(); + response += "

"; + response += "Here is your accees token :
" + oAuth2AccessToken.getTokenValue(); + response += "
"; + response += "
You can use it to call these Resource Server APIs:"; + response += "

"; + response += "Call Resource Server Read API"; + response += "
"; + response += "Call Resource Server Write API"; + return response; + } + + @RequestMapping("/read") + public String read(OAuth2AuthenticationToken authenticationToken) { + String url = remoteResourceServer + "/read"; + return callResourceServer(authenticationToken, url); + } + + @RequestMapping("/write") + public String write(OAuth2AuthenticationToken authenticationToken) { + String url = remoteResourceServer + "/write"; + return callResourceServer(authenticationToken, url); + } + + private String callResourceServer(OAuth2AuthenticationToken authenticationToken, String url) { + OAuth2AuthorizedClient oAuth2AuthorizedClient = this.authorizedClientService.loadAuthorizedClient(authenticationToken.getAuthorizedClientRegistrationId(), authenticationToken.getName()); + OAuth2AccessToken oAuth2AccessToken = oAuth2AuthorizedClient.getAccessToken(); + + HttpHeaders headers = new HttpHeaders(); + headers.add("Authorization", "Bearer " + oAuth2AccessToken.getTokenValue()); + + HttpEntity entity = new HttpEntity<>("parameters", headers); + ResponseEntity responseEntity = null; + + String response = null; + try { + responseEntity = restTemplate.exchange(url, HttpMethod.GET, entity, String.class); + response = responseEntity.getBody(); + } catch (HttpClientErrorException e) { + response = e.getMessage(); + } + return response; + } +} \ No newline at end of file diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties new file mode 100644 index 0000000000..de8e1a7b9f --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties @@ -0,0 +1,23 @@ +# SECURITY OAUTH2 CLIENT (OAuth2ClientProperties) +#spring.security.oauth2.client.provider.*= # OAuth provider details. +#spring.security.oauth2.client.registration.*= # OAuth client registrations. + +server.port=8081 +#server.servlet.context-path=/uaa-client-webapp + +uaa.url=http://localhost:8080/uaa +resource.server.url=http://localhost:8082 + +spring.security.oauth2.client.registration.uaa.client-name=UAA OAuth2 Client +spring.security.oauth2.client.registration.uaa.client-id=client1 +spring.security.oauth2.client.registration.uaa.client-secret=client1 +spring.security.oauth2.client.registration.uaa.authorization-grant-type=authorization_code +spring.security.oauth2.client.registration.uaa.scope=resource.read,resource.write,openid,profile +spring.security.oauth2.client.registration.uaa.redirect-uri=http://localhost:8081/login/oauth2/code/uaa +#spring.security.oauth2.client.registration.uaa.redirect-uri=http://localhost:8081/** + +spring.security.oauth2.client.provider.uaa.token-uri=${uaa.url}/oauth/token +spring.security.oauth2.client.provider.uaa.authorization-uri=${uaa.url}/oauth/authorize +spring.security.oauth2.client.provider.uaa.jwk-set-uri=${uaa.url}/token_keys +spring.security.oauth2.client.provider.uaa.user-info-uri=${uaa.url}/userinfo +spring.security.oauth2.client.provider.uaa.user-name-attribute=user_name diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/templates/index.html b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/templates/index.html new file mode 100644 index 0000000000..eb6e267b94 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/templates/index.html @@ -0,0 +1 @@ +tintin \ No newline at end of file diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml new file mode 100644 index 0000000000..9cf8993cd2 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + com.baeldung.cfuaa + cf-uaa-oauth2-resource-server + 0.0.1-SNAPSHOT + cf-uaa-oauth2-resource-server + Demo project for Spring Boot + + + 1.8 + + + + + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + + + org.springframework.boot + spring-boot-starter-web + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerApplication.java b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerApplication.java new file mode 100644 index 0000000000..51ad6e938d --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.cfuaa.oauth2.resourceserver; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CFUAAOAuth2ResourceServerApplication { + + public static void main(String[] args) { + SpringApplication.run(CFUAAOAuth2ResourceServerApplication.class, args); + } + +} diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerRestController.java b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerRestController.java new file mode 100644 index 0000000000..c08f17d8d8 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerRestController.java @@ -0,0 +1,28 @@ +package com.baeldung.cfuaa.oauth2.resourceserver; + +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.security.Principal; + +@RestController +public class CFUAAOAuth2ResourceServerRestController { + + @GetMapping("/") + public String index(@AuthenticationPrincipal Jwt jwt) { + return String.format("Hello, %s!", jwt.getSubject()); + } + + @GetMapping("/read") + public String read(JwtAuthenticationToken jwtAuthenticationToken) { + return "Hello write: " + jwtAuthenticationToken.getTokenAttributes(); + } + + @GetMapping("/write") + public String write(Principal principal) { + return "Hello write: " + principal.getName(); + } +} diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java new file mode 100644 index 0000000000..d04d51cda3 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java @@ -0,0 +1,21 @@ +package com.baeldung.cfuaa.oauth2.resourceserver; + +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; + +@EnableWebSecurity +public class CFUAAOAuth2ResourceServerSecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .antMatchers("/read/**").hasAuthority("SCOPE_resource.read") + .antMatchers("/write/**").hasAuthority("SCOPE_resource.write") + .anyRequest().authenticated() + .and() + .oauth2ResourceServer() + .jwt(); + } +} \ No newline at end of file diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/resources/application.properties b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/resources/application.properties new file mode 100644 index 0000000000..ba9b95e0d4 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/resources/application.properties @@ -0,0 +1,16 @@ +server.port=8082 + +uaa.url=http://localhost:8080/uaa + +#approch1 +spring.security.oauth2.resourceserver.jwt.issuer-uri=${uaa.url}/oauth/token + +#approch2 +#spring.security.oauth2.resourceserver.jwt.jwk-set-uri=${uaa.url}/token_key + +# SECURITY OAUTH2 CLIENT (OAuth2ClientProperties) +#security.oauth2.client.client-id=client1 +#security.oauth2.client.client-secret=client1 + +#security.oauth2.resource.jwt.key-uri=${uaa.url}/token_key +#security.oauth2.resource.token-info-uri=${uaa.url}/oauth/check_token diff --git a/core-groovy/README.md b/core-groovy/README.md index 71788acdb7..ec2fcfa574 100644 --- a/core-groovy/README.md +++ b/core-groovy/README.md @@ -4,3 +4,7 @@ - [JDBC with Groovy](http://www.baeldung.com/jdbc-groovy) - [Working with JSON in Groovy](http://www.baeldung.com/groovy-json) +- [Reading a File in Groovy](https://www.baeldung.com/groovy-file-read) +- [Types of Strings in Groovy](https://www.baeldung.com/groovy-strings) +- [A Quick Guide to Iterating a Map in Groovy](https://www.baeldung.com/groovy-map-iterating) +- [An Introduction to Traits in Groovy](https://www.baeldung.com/groovy-traits) diff --git a/core-groovy/src/main/groovy/com/baeldung/io/Task.groovy b/core-groovy/src/main/groovy/com/baeldung/io/Task.groovy new file mode 100644 index 0000000000..8a3bedc048 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/io/Task.groovy @@ -0,0 +1,8 @@ +package com.baeldung.io + +class Task implements Serializable { + String description + Date startDate + Date dueDate + int status +} diff --git a/core-groovy/src/main/resources/binaryExample.jpg b/core-groovy/src/main/resources/binaryExample.jpg new file mode 100644 index 0000000000..4b32645ac9 Binary files /dev/null and b/core-groovy/src/main/resources/binaryExample.jpg differ diff --git a/core-groovy/src/main/resources/ioData.txt b/core-groovy/src/main/resources/ioData.txt new file mode 100644 index 0000000000..d2741339d1 Binary files /dev/null and b/core-groovy/src/main/resources/ioData.txt differ diff --git a/core-groovy/src/main/resources/ioInput.txt b/core-groovy/src/main/resources/ioInput.txt new file mode 100644 index 0000000000..b180256dd5 --- /dev/null +++ b/core-groovy/src/main/resources/ioInput.txt @@ -0,0 +1,4 @@ +First line of text +Second line of text +Third line of text +Fourth line of text \ No newline at end of file diff --git a/core-groovy/src/main/resources/ioOutput.txt b/core-groovy/src/main/resources/ioOutput.txt new file mode 100644 index 0000000000..bcf76c43d8 --- /dev/null +++ b/core-groovy/src/main/resources/ioOutput.txt @@ -0,0 +1,3 @@ +Line one of output example +Line two of output example +Line three of output example \ No newline at end of file diff --git a/core-groovy/src/main/resources/ioSerializedObject.txt b/core-groovy/src/main/resources/ioSerializedObject.txt new file mode 100644 index 0000000000..833ed32bf1 Binary files /dev/null and b/core-groovy/src/main/resources/ioSerializedObject.txt differ diff --git a/core-groovy/src/test/groovy/com/baeldung/io/DataAndObjectsUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/io/DataAndObjectsUnitTest.groovy new file mode 100644 index 0000000000..0b413cf76c --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/io/DataAndObjectsUnitTest.groovy @@ -0,0 +1,51 @@ +package com.baeldung.io + +import static org.junit.Assert.* + +import org.junit.Test + +class DataAndObjectsUnitTest { + @Test + void whenUsingWithDataOutputStream_thenDataIsSerializedToAFile() { + String message = 'This is a serialized string' + int length = message.length() + boolean valid = true + new File('src/main/resources/ioData.txt').withDataOutputStream { out -> + out.writeUTF(message) + out.writeInt(length) + out.writeBoolean(valid) + } + + String loadedMessage = "" + int loadedLength + boolean loadedValid + + new File('src/main/resources/ioData.txt').withDataInputStream { is -> + loadedMessage = is.readUTF() + loadedLength = is.readInt() + loadedValid = is.readBoolean() + } + + assertEquals(message, loadedMessage) + assertEquals(length, loadedLength) + assertEquals(valid, loadedValid) + } + + @Test + void whenUsingWithObjectOutputStream_thenObjectIsSerializedToFile() { + Task task = new Task(description:'Take out the trash', startDate:new Date(), status:0) + new File('src/main/resources/ioSerializedObject.txt').withObjectOutputStream { out -> + out.writeObject(task) + } + + Task taskRead + + new File('src/main/resources/ioSerializedObject.txt').withObjectInputStream { is -> + taskRead = is.readObject() + } + + assertEquals(task.description, taskRead.description) + assertEquals(task.startDate, taskRead.startDate) + assertEquals(task.status, taskRead.status) + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/io/ReadExampleUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/io/ReadExampleUnitTest.groovy new file mode 100644 index 0000000000..bed77b4d81 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/io/ReadExampleUnitTest.groovy @@ -0,0 +1,134 @@ +package com.baeldung.io + +import static org.junit.Assert.* +import org.junit.Test + +class ReadExampleUnitTest { + + @Test + void whenUsingEachLine_thenCorrectLinesReturned() { + def expectedList = [ + 'First line of text', + 'Second line of text', + 'Third line of text', + 'Fourth line of text'] + + def lines = [] + + new File('src/main/resources/ioInput.txt').eachLine { line -> + lines.add(line) + } + assertEquals(expectedList, lines) + } + + @Test + void whenUsingReadEachLineWithLineNumber_thenCorrectLinesReturned() { + def expectedList = [ + 'Second line of text', + 'Third line of text', + 'Fourth line of text'] + + def lineNoRange = 2..4 + def lines = [] + + new File('src/main/resources/ioInput.txt').eachLine { line, lineNo -> + if (lineNoRange.contains(lineNo)) { + lines.add(line) + } + } + assertEquals(expectedList, lines) + } + + @Test + void whenUsingReadEachLineWithLineNumberStartAtZero_thenCorrectLinesReturned() { + def expectedList = [ + 'Second line of text', + 'Third line of text', + 'Fourth line of text'] + + def lineNoRange = 1..3 + def lines = [] + + new File('src/main/resources/ioInput.txt').eachLine(0, { line, lineNo -> + if (lineNoRange.contains(lineNo)) { + lines.add(line) + } + }) + assertEquals(expectedList, lines) + } + + @Test + void whenUsingWithReader_thenLineCountReturned() { + def expectedCount = 4 + def actualCount = 0 + new File('src/main/resources/ioInput.txt').withReader { reader -> + while(reader.readLine()) { + actualCount++ + } + } + assertEquals(expectedCount, actualCount) + } + + @Test + void whenUsingNewReader_thenOutputFileCreated() { + def outputPath = 'src/main/resources/ioOut.txt' + def reader = new File('src/main/resources/ioInput.txt').newReader() + new File(outputPath).append(reader) + reader.close() + def ioOut = new File(outputPath) + assertTrue(ioOut.exists()) + ioOut.delete() + } + + @Test + void whenUsingWithInputStream_thenCorrectBytesAreReturned() { + def expectedLength = 1139 + byte[] data = [] + new File("src/main/resources/binaryExample.jpg").withInputStream { stream -> + data = stream.getBytes() + } + assertEquals(expectedLength, data.length) + } + + @Test + void whenUsingNewInputStream_thenOutputFileCreated() { + def outputPath = 'src/main/resources/binaryOut.jpg' + def is = new File('src/main/resources/binaryExample.jpg').newInputStream() + new File(outputPath).append(is) + is.close() + def ioOut = new File(outputPath) + assertTrue(ioOut.exists()) + ioOut.delete() + } + + @Test + void whenUsingCollect_thenCorrectListIsReturned() { + def expectedList = ['First line of text', 'Second line of text', 'Third line of text', 'Fourth line of text'] + + def actualList = new File('src/main/resources/ioInput.txt').collect {it} + assertEquals(expectedList, actualList) + } + + @Test + void whenUsingAsStringArray_thenCorrectArrayIsReturned() { + String[] expectedArray = ['First line of text', 'Second line of text', 'Third line of text', 'Fourth line of text'] + + def actualArray = new File('src/main/resources/ioInput.txt') as String[] + assertArrayEquals(expectedArray, actualArray) + } + + @Test + void whenUsingText_thenCorrectStringIsReturned() { + def ln = System.getProperty('line.separator') + def expectedString = "First line of text${ln}Second line of text${ln}Third line of text${ln}Fourth line of text" + def actualString = new File('src/main/resources/ioInput.txt').text + assertEquals(expectedString.toString(), actualString) + } + + @Test + void whenUsingBytes_thenByteArrayIsReturned() { + def expectedLength = 1139 + def contents = new File('src/main/resources/binaryExample.jpg').bytes + assertEquals(expectedLength, contents.length) + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/io/TraverseFileTreeUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/io/TraverseFileTreeUnitTest.groovy new file mode 100644 index 0000000000..dac0189fb9 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/io/TraverseFileTreeUnitTest.groovy @@ -0,0 +1,61 @@ +package com.baeldung.io + +import org.junit.Test + +import groovy.io.FileType +import groovy.io.FileVisitResult + +class TraverseFileTreeUnitTest { + @Test + void whenUsingEachFile_filesAreListed() { + new File('src/main/resources').eachFile { file -> + println file.name + } + } + + @Test(expected = IllegalArgumentException) + void whenUsingEachFileOnAFile_anErrorOccurs() { + new File('src/main/resources/ioInput.txt').eachFile { file -> + println file.name + } + } + + @Test + void whenUsingEachFileMatch_filesAreListed() { + new File('src/main/resources').eachFileMatch(~/io.*\.txt/) { file -> + println file.name + } + } + + @Test + void whenUsingEachFileRecurse_thenFilesInSubfoldersAreListed() { + new File('src/main').eachFileRecurse(FileType.FILES) { file -> + println "$file.parent $file.name" + } + } + + @Test + void whenUsingEachFileRecurse_thenDirsInSubfoldersAreListed() { + new File('src/main').eachFileRecurse(FileType.DIRECTORIES) { file -> + println "$file.parent $file.name" + } + } + + @Test + void whenUsingEachDirRecurse_thenDirsAndSubDirsAreListed() { + new File('src/main').eachDirRecurse { dir -> + println "$dir.parent $dir.name" + } + } + + @Test + void whenUsingTraverse_thenDirectoryIsTraversed() { + new File('src/main').traverse { file -> + if (file.directory && file.name == 'groovy') { + FileVisitResult.SKIP_SUBTREE + } else { + println "$file.parent - $file.name" + } + } + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/io/WriteExampleUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/io/WriteExampleUnitTest.groovy new file mode 100644 index 0000000000..81758b430a --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/io/WriteExampleUnitTest.groovy @@ -0,0 +1,96 @@ +package com.baeldung.io + +import static org.junit.Assert.* + +import org.junit.Before +import org.junit.Test + +class WriteExampleUnitTest { + @Before + void clearOutputFile() { + new File('src/main/resources/ioOutput.txt').text = '' + new File('src/main/resources/ioBinaryOutput.bin').delete() + } + + @Test + void whenUsingWithWriter_thenFileCreated() { + def outputLines = [ + 'Line one of output example', + 'Line two of output example', + 'Line three of output example' + ] + + def outputFileName = 'src/main/resources/ioOutput.txt' + new File(outputFileName).withWriter { writer -> + outputLines.each { line -> + writer.writeLine line + } + } + def writtenLines = new File(outputFileName).collect {it} + assertEquals(outputLines, writtenLines) + } + + @Test + void whenUsingNewWriter_thenFileCreated() { + def outputLines = [ + 'Line one of output example', + 'Line two of output example', + 'Line three of output example' + ] + + def outputFileName = 'src/main/resources/ioOutput.txt' + def writer = new File(outputFileName).newWriter() + outputLines.forEach {line -> + writer.writeLine line + } + writer.flush() + writer.close() + + def writtenLines = new File(outputFileName).collect {it} + assertEquals(outputLines, writtenLines) + } + + @Test + void whenUsingDoubleLessThanOperator_thenFileCreated() { + def outputLines = [ + 'Line one of output example', + 'Line two of output example', + 'Line three of output example' + ] + + def ln = System.getProperty('line.separator') + def outputFileName = 'src/main/resources/ioOutput.txt' + new File(outputFileName) << "Line one of output example${ln}Line two of output example${ln}Line three of output example" + def writtenLines = new File(outputFileName).collect {it} + assertEquals(outputLines.size(), writtenLines.size()) + } + + @Test + void whenUsingBytes_thenBinaryFileCreated() { + def outputFileName = 'src/main/resources/ioBinaryOutput.bin' + def outputFile = new File(outputFileName) + byte[] outBytes = [44, 88, 22] + outputFile.bytes = outBytes + assertEquals(3, new File(outputFileName).size()) + } + + @Test + void whenUsingWithOutputStream_thenBinaryFileCreated() { + def outputFileName = 'src/main/resources/ioBinaryOutput.bin' + byte[] outBytes = [44, 88, 22] + new File(outputFileName).withOutputStream { stream -> + stream.write(outBytes) + } + assertEquals(3, new File(outputFileName).size()) + } + + @Test + void whenUsingNewOutputStream_thenBinaryFileCreated() { + def outputFileName = 'src/main/resources/ioBinaryOutput.bin' + byte[] outBytes = [44, 88, 22] + def os = new File(outputFileName).newOutputStream() + os.write(outBytes) + os.close() + assertEquals(3, new File(outputFileName).size()) + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy b/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy new file mode 100644 index 0000000000..f682503ed4 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy @@ -0,0 +1,173 @@ +package com.baeldung.groovy.lists + +import static groovy.test.GroovyAssert.* +import org.junit.Test + +class ListTest{ + + @Test + void testCreateList() { + + def list = [1, 2, 3] + assertNotNull(list) + + def listMix = ['A', "b", 1, true] + assertTrue(listMix == ['A', "b", 1, true]) + + def linkedList = [1, 2, 3] as LinkedList + assertTrue(linkedList instanceof LinkedList) + + ArrayList arrList = [1, 2, 3] + assertTrue(arrList.class == ArrayList) + + def copyList = new ArrayList(arrList) + assertTrue(copyList == arrList) + + def cloneList = arrList.clone() + assertTrue(cloneList == arrList) + } + + @Test + void testCreateEmptyList() { + + def emptyList = [] + assertTrue(emptyList.size() == 0) + } + + @Test + void testCompareTwoLists() { + + def list1 = [5, 6.0, 'p'] + def list2 = [5, 6.0, 'p'] + assertTrue(list1 == list2) + } + + @Test + void testGetItemsFromList(){ + + def list = ["Hello", "World"] + + assertTrue(list.get(1) == "World") + assertTrue(list[1] == "World") + assertTrue(list[-1] == "World") + assertTrue(list.getAt(1) == "World") + assertTrue(list.getAt(-2) == "Hello") + } + + @Test + void testAddItemsToList() { + + def list = [] + + list << 1 + list.add("Apple") + assertTrue(list == [1, "Apple"]) + + list[2] = "Box" + list[4] = true + assertTrue(list == [1, "Apple", "Box", null, true]) + + list.add(1, 6.0) + assertTrue(list == [1, 6.0, "Apple", "Box", null, true]) + + def list2 = [1, 2] + list += list2 + list += 12 + assertTrue(list == [1, 6.0, "Apple", "Box", null, true, 1, 2, 12]) + } + + @Test + void testUpdateItemsInList() { + + def list =[1, "Apple", 80, "App"] + list[1] = "Box" + list.set(2,90) + assertTrue(list == [1, "Box", 90, "App"]) + } + + @Test + void testRemoveItemsFromList(){ + + def list = [1, 2, 3, 4, 5, 5, 6, 6, 7] + + list.remove(3) + assertTrue(list == [1, 2, 3, 5, 5, 6, 6, 7]) + + list.removeElement(5) + assertTrue(list == [1, 2, 3, 5, 6, 6, 7]) + + assertTrue(list - 6 == [1, 2, 3, 5, 7]) + } + + @Test + void testIteratingOnAList(){ + + def list = [1, "App", 3, 4] + list.each{ println it * 2} + + list.eachWithIndex{ it, i -> println "$i : $it" } + } + + @Test + void testCollectingToAnotherList(){ + + def list = ["Kay", "Henry", "Justin", "Tom"] + assertTrue(list.collect{"Hi " + it} == ["Hi Kay", "Hi Henry", "Hi Justin", "Hi Tom"]) + } + + @Test + void testJoinItemsInAList(){ + assertTrue(["One", "Two", "Three"].join(",") == "One,Two,Three") + } + + @Test + void testFilteringOnLists(){ + def filterList = [2, 1, 3, 4, 5, 6, 76] + + assertTrue(filterList.find{it > 3} == 4) + + assertTrue(filterList.findAll{it > 3} == [4, 5, 6, 76]) + + assertTrue(filterList.findAll{ it instanceof Number} == [2, 1, 3, 4, 5, 6, 76]) + + assertTrue(filterList.grep( Number )== [2, 1, 3, 4, 5, 6, 76]) + + assertTrue(filterList.grep{ it> 6 }== [76]) + + def conditionList = [2, 1, 3, 4, 5, 6, 76] + + assertFalse(conditionList.every{ it < 6}) + + assertTrue(conditionList.any{ it%2 == 0}) + + } + + @Test + void testGetUniqueItemsInAList(){ + assertTrue([1, 3, 3, 4].toUnique() == [1, 3, 4]) + + def uniqueList = [1, 3, 3, 4] + uniqueList.unique() + assertTrue(uniqueList == [1, 3, 4]) + + assertTrue(["A", "B", "Ba", "Bat", "Cat"].toUnique{ it.size()} == ["A", "Ba", "Bat"]) + } + + @Test + void testSorting(){ + + assertTrue([1, 2, 1, 0].sort() == [0, 1, 1, 2]) + Comparator mc = {a,b -> a == b? 0: a < b? 1 : -1} + + def list = [1, 2, 1, 0] + list.sort(mc) + assertTrue(list == [2, 1, 1, 0]) + + def strList = ["na", "ppp", "as"] + assertTrue(strList.max() == "ppp") + + Comparator minc = {a,b -> a == b? 0: a < b? -1 : 1} + def numberList = [3, 2, 0, 7] + assertTrue(numberList.min(minc) == 0) + } +} \ No newline at end of file diff --git a/core-java-8/README.md b/core-java-8/README.md index 892dc71f76..99182da390 100644 --- a/core-java-8/README.md +++ b/core-java-8/README.md @@ -4,9 +4,9 @@ ### Relevant Articles: - [Java 8 Collectors](http://www.baeldung.com/java-8-collectors) -- [Guide to Java 8’s Functional Interfaces](http://www.baeldung.com/java-8-functional-interfaces) +- [Functional Interfaces in Java 8](http://www.baeldung.com/java-8-functional-interfaces) - [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda) -- [Java 8 New Features](http://www.baeldung.com/java-8-new-features) +- [New Features in Java 8](http://www.baeldung.com/java-8-new-features) - [Lambda Expressions and Functional Interfaces: Tips and Best Practices](http://www.baeldung.com/java-8-lambda-expressions-tips) - [The Double Colon Operator in Java 8](http://www.baeldung.com/java-8-double-colon-operator) - [Guide to Java 8 groupingBy Collector](http://www.baeldung.com/java-groupingby-collector) @@ -38,3 +38,5 @@ - [Java @SafeVarargs Annotation](https://www.baeldung.com/java-safevarargs) - [Java @Deprecated Annotation](https://www.baeldung.com/java-deprecated) - [Java 8 Predicate Chain](https://www.baeldung.com/java-predicate-chain) +- [Method References in Java](https://www.baeldung.com/java-method-references) +- [Creating a Custom Annotation in Java](https://www.baeldung.com/java-custom-annotation) diff --git a/core-java-9/README.md b/core-java-9/README.md index d9586ba684..224306db19 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -16,7 +16,7 @@ - [Java 9 Reactive Streams](http://www.baeldung.com/java-9-reactive-streams) - [Java 9 java.util.Objects Additions](http://www.baeldung.com/java-9-objects-new) - [Java 9 Variable Handles Demistyfied](http://www.baeldung.com/java-variable-handles) -- [Exploring the New HTTP Client in Java 9](http://www.baeldung.com/java-9-http-client) +- [Exploring the New HTTP Client in Java 9 and 11](http://www.baeldung.com/java-9-http-client) - [Method Handles in Java](http://www.baeldung.com/java-method-handles) - [Introduction to Chronicle Queue](http://www.baeldung.com/java-chronicle-queue) - [A Guide to Java 9 Modularity](http://www.baeldung.com/java-9-modularity) @@ -27,3 +27,5 @@ - [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) +- [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar) +- [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation) diff --git a/core-java-9/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java b/core-java-9/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java new file mode 100644 index 0000000000..0458383e99 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java @@ -0,0 +1,182 @@ +package com.baeldung.processbuilder; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.ProcessBuilder.Redirect; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +public class ProcessBuilderUnitTest { + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + + @Test + public void givenProcessBuilder_whenInvokeStart_thenSuccess() throws IOException, InterruptedException, ExecutionException { + ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); + processBuilder.redirectErrorStream(true); + + Process process = processBuilder.start(); + + List results = readOutput(process.getInputStream()); + assertThat("Results should not be empty", results, is(not(empty()))); + assertThat("Results should contain java version: ", results, hasItem(containsString("java version"))); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + } + + @Test + public void givenProcessBuilder_whenModifyEnvironment_thenSuccess() throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder(); + Map environment = processBuilder.environment(); + environment.forEach((key, value) -> System.out.println(key + value)); + + environment.put("GREETING", "Hola Mundo"); + + List command = getGreetingCommand(); + processBuilder.command(command); + Process process = processBuilder.start(); + + List results = readOutput(process.getInputStream()); + assertThat("Results should not be empty", results, is(not(empty()))); + assertThat("Results should contain a greeting ", results, hasItem(containsString("Hola Mundo"))); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + } + + @Test + public void givenProcessBuilder_whenModifyWorkingDir_thenSuccess() throws IOException, InterruptedException { + List command = getDirectoryListingCommand(); + ProcessBuilder processBuilder = new ProcessBuilder(command); + + processBuilder.directory(new File("src")); + Process process = processBuilder.start(); + + List results = readOutput(process.getInputStream()); + assertThat("Results should not be empty", results, is(not(empty()))); + assertThat("Results should contain directory listing: ", results, hasItems(containsString("main"), containsString("test"))); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + } + + @Test + public void givenProcessBuilder_whenRedirectStandardOutput_thenSuccessWriting() throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); + + processBuilder.redirectErrorStream(true); + File log = tempFolder.newFile("java-version.log"); + processBuilder.redirectOutput(log); + + Process process = processBuilder.start(); + + assertEquals("If redirected, should be -1 ", -1, process.getInputStream() + .read()); + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + + List lines = Files.lines(log.toPath()) + .collect(Collectors.toList()); + + assertThat("Results should not be empty", lines, is(not(empty()))); + assertThat("Results should contain java version: ", lines, hasItem(containsString("java version"))); + } + + @Test + public void givenProcessBuilder_whenRedirectStandardOutput_thenSuccessAppending() throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); + + File log = tempFolder.newFile("java-version-append.log"); + processBuilder.redirectErrorStream(true); + processBuilder.redirectOutput(Redirect.appendTo(log)); + + Process process = processBuilder.start(); + + assertEquals("If redirected output, should be -1 ", -1, process.getInputStream() + .read()); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + + List lines = Files.lines(log.toPath()) + .collect(Collectors.toList()); + + assertThat("Results should not be empty", lines, is(not(empty()))); + assertThat("Results should contain java version: ", lines, hasItem(containsString("java version"))); + } + + @Test + public void givenProcessBuilder_whenStartingPipeline_thenSuccess() throws IOException, InterruptedException { + if (!isWindows()) { + List builders = Arrays.asList( + new ProcessBuilder("find", "src", "-name", "*.java", "-type", "f"), + new ProcessBuilder("wc", "-l")); + + List processes = ProcessBuilder.startPipeline(builders); + Process last = processes.get(processes.size() - 1); + + List output = readOutput(last.getInputStream()); + assertThat("Results should not be empty", output, is(not(empty()))); + } + } + + @Test + public void givenProcessBuilder_whenInheritIO_thenSuccess() throws IOException, InterruptedException { + List command = getEchoCommand(); + ProcessBuilder processBuilder = new ProcessBuilder(command); + + processBuilder.inheritIO(); + Process process = processBuilder.start(); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + } + + private List readOutput(InputStream inputStream) throws IOException { + try (BufferedReader output = new BufferedReader(new InputStreamReader(inputStream))) { + return output.lines() + .collect(Collectors.toList()); + } + } + + private List getDirectoryListingCommand() { + return isWindows() ? Arrays.asList("cmd.exe", "/c", "dir") : Arrays.asList("/bin/sh", "-c", "ls"); + } + + private List getGreetingCommand() { + return isWindows() ? Arrays.asList("cmd.exe", "/c", "echo %GREETING%") : Arrays.asList("/bin/bash", "-c", "echo $GREETING"); + } + + private List getEchoCommand() { + return isWindows() ? Arrays.asList("cmd.exe", "/c", "echo hello") : Arrays.asList("/bin/sh", "-c", "echo hello"); + } + + private boolean isWindows() { + return System.getProperty("os.name") + .toLowerCase() + .startsWith("windows"); + } + +} diff --git a/core-java-collections-list/README.md b/core-java-collections-list/README.md index 3a4a7c69e8..c5139074e9 100644 --- a/core-java-collections-list/README.md +++ b/core-java-collections-list/README.md @@ -5,7 +5,7 @@ ### Relevant Articles: - [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list) - [Guide to the Java ArrayList](http://www.baeldung.com/java-arraylist) -- [Random List Element](http://www.baeldung.com/java-random-list-element) +- [Java – Get Random Item/Element From a List](http://www.baeldung.com/java-random-list-element) - [Removing all nulls from a List in Java](http://www.baeldung.com/java-remove-nulls-from-list) - [Removing all duplicates from a List in Java](http://www.baeldung.com/java-remove-duplicates-from-list) - [How to TDD a List Implementation in Java](http://www.baeldung.com/java-test-driven-list) @@ -28,3 +28,5 @@ - [Intersection of Two Lists in Java](https://www.baeldung.com/java-lists-intersection) - [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist) - [Determine If All Elements Are the Same in a Java List](https://www.baeldung.com/java-list-all-equal) +- [List of Primitive Integer Values in Java](https://www.baeldung.com/java-list-primitive-int) +- [Performance Comparison of Primitive Lists in Java](https://www.baeldung.com/java-list-primitive-performance) diff --git a/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/Employee.java b/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/Employee.java new file mode 100644 index 0000000000..2aa267b4dc --- /dev/null +++ b/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/Employee.java @@ -0,0 +1,44 @@ +package com.baeldung.collection.filtering; + +/** + * Java 8 Collection Filtering by List of Values base class. + * + * @author Rodolfo Felipe + */ +public class Employee { + + private Integer employeeNumber; + private String name; + private Integer departmentId; + + public Employee(Integer employeeNumber, String name, Integer departmentId) { + this.employeeNumber = employeeNumber; + this.name = name; + this.departmentId = departmentId; + } + + public Integer getEmployeeNumber() { + return employeeNumber; + } + + public void setEmployeeNumber(Integer employeeNumber) { + this.employeeNumber = employeeNumber; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getDepartmentId() { + return departmentId; + } + + public void setDepartmentId(Integer departmentId) { + this.departmentId = departmentId; + } + +} diff --git a/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java new file mode 100644 index 0000000000..cbc7136192 --- /dev/null +++ b/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java @@ -0,0 +1,73 @@ +package com.baeldung.collection.filtering; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; + +/** + * Various filtering examples. + * + * @author Rodolfo Felipe + */ +public class CollectionFilteringUnitTest { + + private List buildEmployeeList() { + return Arrays.asList(new Employee(1, "Mike", 1), new Employee(2, "John", 1), new Employee(3, "Mary", 1), new Employee(4, "Joe", 2), new Employee(5, "Nicole", 2), new Employee(6, "Alice", 2), new Employee(7, "Bob", 3), new Employee(8, "Scarlett", 3)); + } + + private List employeeNameFilter() { + return Arrays.asList("Alice", "Mike", "Bob"); + } + + @Test + public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingForEachLoop() { + List filteredList = new ArrayList<>(); + List originalList = buildEmployeeList(); + List nameFilter = employeeNameFilter(); + + for (Employee employee : originalList) { + for (String name : nameFilter) { + if (employee.getName() + .equalsIgnoreCase(name)) { + filteredList.add(employee); + } + } + } + + Assert.assertThat(filteredList.size(), Matchers.is(nameFilter.size())); + } + + @Test + public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambda() { + List filteredList; + List originalList = buildEmployeeList(); + List nameFilter = employeeNameFilter(); + + filteredList = originalList.stream() + .filter(employee -> nameFilter.contains(employee.getName())) + .collect(Collectors.toList()); + + Assert.assertThat(filteredList.size(), Matchers.is(nameFilter.size())); + } + + @Test + public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambdaAndHashSet() { + List filteredList; + List originalList = buildEmployeeList(); + Set nameFilterSet = employeeNameFilter().stream() + .collect(Collectors.toSet()); + + filteredList = originalList.stream() + .filter(employee -> nameFilterSet.contains(employee.getName())) + .collect(Collectors.toList()); + + Assert.assertThat(filteredList.size(), Matchers.is(nameFilterSet.size())); + } + +} diff --git a/core-java-collections/README.md b/core-java-collections/README.md index 710be31a08..80d4385c45 100644 --- a/core-java-collections/README.md +++ b/core-java-collections/README.md @@ -32,3 +32,4 @@ - [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) +- [Defining a Char Stack in Java](https://www.baeldung.com/java-char-stack) diff --git a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java index a1d40657d3..b93f8e9cc2 100644 --- a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java +++ b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java @@ -1,17 +1,21 @@ package com.baeldung.performance; -import org.openjdk.jmh.annotations.*; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.TimeUnit; - -@BenchmarkMode(Mode.SingleShotTime) +@BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) @Measurement(batchSize = 100000, iterations = 10) @Warmup(batchSize = 100000, iterations = 10) @@ -19,8 +23,8 @@ public class ArraySortBenchmark { @State(Scope.Thread) public static class Initialize { - Integer[] numbers = {5, 22, 10, 0}; - int[] primitives = {5, 22, 10, 0}; + Integer[] numbers = { -769214442, -1283881723, 1504158300, -1260321086, -1800976432, 1278262737, 1863224321, 1895424914, 2062768552, -1051922993, 751605209, -1500919212, 2094856518, -1014488489, -931226326, -1677121986, -2080561705, 562424208, -1233745158, 41308167 }; + int[] primitives = { -769214442, -1283881723, 1504158300, -1260321086, -1800976432, 1278262737, 1863224321, 1895424914, 2062768552, -1051922993, 751605209, -1500919212, 2094856518, -1014488489, -931226326, -1677121986, -2080561705, 562424208, -1233745158, 41308167 }; } @Benchmark diff --git a/core-java-io/README.md b/core-java-io/README.md index 9a25009849..5e0f7bfbd1 100644 --- a/core-java-io/README.md +++ b/core-java-io/README.md @@ -3,7 +3,7 @@ ## Core Java IO Cookbooks and Examples ### Relevant Articles: -- [Java - Reading a Large File Efficiently](http://www.baeldung.com/java-read-lines-large-file) +- [How to Read a Large File Efficiently with Java](http://www.baeldung.com/java-read-lines-large-file) - [Java InputStream to String](http://www.baeldung.com/convert-input-stream-to-string) - [Java – Write to File](http://www.baeldung.com/java-write-to-file) - [Java - Convert File to InputStream](http://www.baeldung.com/convert-file-to-input-stream) @@ -11,7 +11,7 @@ - [Java – Byte Array to Writer](http://www.baeldung.com/java-convert-byte-array-to-writer) - [Java – Directory Size](http://www.baeldung.com/java-folder-size) - [Differences Between the Java WatchService API and the Apache Commons IO Monitor Library](http://www.baeldung.com/java-watchservice-vs-apache-commons-io-monitor-library) -- [Calculate the Size of a File in Java](http://www.baeldung.com/java-file-size) +- [File Size in Java](http://www.baeldung.com/java-file-size) - [Comparing getPath(), getAbsolutePath(), and getCanonicalPath() in Java](http://www.baeldung.com/java-path) - [Using Java MappedByteBuffer](http://www.baeldung.com/java-mapped-byte-buffer) - [Copy a File with Java](http://www.baeldung.com/java-copy-file) diff --git a/core-java-lang-oop/README.md b/core-java-lang-oop/README.md index bbc3d26c99..200415fe21 100644 --- a/core-java-lang-oop/README.md +++ b/core-java-lang-oop/README.md @@ -22,3 +22,4 @@ - [Inheritance and Composition (Is-a vs Has-a relationship) in Java](http://www.baeldung.com/java-inheritance-composition) - [A Guide to Constructors in Java](https://www.baeldung.com/java-constructors) - [Java equals() and hashCode() Contracts](https://www.baeldung.com/java-equals-hashcode-contracts) +- [Marker Interfaces in Java](https://www.baeldung.com/java-marker-interfaces) diff --git a/core-java-lang-syntax/README.md b/core-java-lang-syntax/README.md index 99c8613929..81c3d6c354 100644 --- a/core-java-lang-syntax/README.md +++ b/core-java-lang-syntax/README.md @@ -3,12 +3,12 @@ ## Core Java Lang Syntax Cookbooks and Examples ### Relevant Articles: -- [Introduction to Java Generics](http://www.baeldung.com/java-generics) +- [The Basics of Java Generics](http://www.baeldung.com/java-generics) - [Java Primitive Conversions](http://www.baeldung.com/java-primitive-conversions) - [Java Double Brace Initialization](http://www.baeldung.com/java-double-brace-initialization) - [Guide to the Diamond Operator in Java](http://www.baeldung.com/java-diamond-operator) - [The Java continue and break Keywords](http://www.baeldung.com/java-continue-and-break) -- [A Guide to Java Initialization](http://www.baeldung.com/java-initialization) +- [A Guide to Creating Objects in Java](http://www.baeldung.com/java-initialization) - [A Guide to Java Loops](http://www.baeldung.com/java-loops) - [Varargs in Java](http://www.baeldung.com/java-varargs) - [A Guide to Java Enums](http://www.baeldung.com/a-guide-to-java-enums) diff --git a/core-java-lang/README.md b/core-java-lang/README.md index c1c22caf6c..eaedc93eed 100644 --- a/core-java-lang/README.md +++ b/core-java-lang/README.md @@ -41,3 +41,4 @@ - [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) +- [Java Classes and Objects](https://www.baeldung.com/java-classes-objects) diff --git a/core-java-networking/README.md b/core-java-networking/README.md index 40be47fbcc..e76f28030d 100644 --- a/core-java-networking/README.md +++ b/core-java-networking/README.md @@ -12,6 +12,6 @@ - [A Guide to the Java URL](http://www.baeldung.com/java-url) - [Working with Network Interfaces in Java](http://www.baeldung.com/java-network-interfaces) - [A Guide to Java Sockets](http://www.baeldung.com/a-guide-to-java-sockets) -- [URL Encoding and Decoding in Java](http://www.baeldung.com/java-url-encoding-decoding) -- [How to Perform a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request) -- [Difference between URL and URI](http://www.baeldung.com/java-url-vs-uri) +- [Guide to Java URL Encoding/Decoding](http://www.baeldung.com/java-url-encoding-decoding) +- [Do a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request) +- [Difference between URL and URI](http://www.baeldung.com/java-url-vs-uri) \ No newline at end of file diff --git a/core-java-security/README.md b/core-java-security/README.md index d3343f79ca..9526b15be5 100644 --- a/core-java-security/README.md +++ b/core-java-security/README.md @@ -8,5 +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) +- [SHA-256 and SHA3-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/README.md b/core-java/README.md index 1143604eac..67538a3895 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -50,3 +50,4 @@ - [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) +- [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar) diff --git a/core-kotlin-2/README.md b/core-kotlin-2/README.md index 6aabd71a6c..8d22c4f1a8 100644 --- a/core-kotlin-2/README.md +++ b/core-kotlin-2/README.md @@ -1,3 +1,4 @@ ## Relevant articles: - [Void Type in Kotlin](https://www.baeldung.com/kotlin-void-type) +- [How to use Kotlin Range Expressions](https://www.baeldung.com/kotlin-ranges) diff --git a/core-kotlin/README.md b/core-kotlin/README.md index 6ee79b2a2e..7d8001d667 100644 --- a/core-kotlin/README.md +++ b/core-kotlin/README.md @@ -4,7 +4,7 @@ - [A guide to the “when{}” block in Kotlin](http://www.baeldung.com/kotlin-when) - [Comprehensive Guide to Null Safety in Kotlin](http://www.baeldung.com/kotlin-null-safety) - [Kotlin Java Interoperability](http://www.baeldung.com/kotlin-java-interoperability) -- [Difference Between “==” and “===” in Kotlin](http://www.baeldung.com/kotlin-equality-operators) +- [Difference Between “==” and “===” operators in Kotlin](http://www.baeldung.com/kotlin-equality-operators) - [Generics in Kotlin](http://www.baeldung.com/kotlin-generics) - [Introduction to Kotlin Coroutines](http://www.baeldung.com/kotlin-coroutines) - [Destructuring Declarations in Kotlin](http://www.baeldung.com/kotlin-destructuring-declarations) @@ -52,3 +52,5 @@ - [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) +- [Building DSLs in Kotlin](https://www.baeldung.com/kotlin-dsl) +- [Static Methods Behavior in Kotlin](https://www.baeldung.com/kotlin-static-methods) diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegation.kt b/core-kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegation.kt new file mode 100644 index 0000000000..8e261aacf2 --- /dev/null +++ b/core-kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegation.kt @@ -0,0 +1,64 @@ +package com.baeldung.kotlin.delegates + +import java.util.concurrent.locks.ReentrantLock +import kotlin.concurrent.withLock + +interface Producer { + + fun produce(): String +} + +class ProducerImpl : Producer { + + override fun produce() = "ProducerImpl" +} + +class EnhancedProducer(private val delegate: Producer) : Producer by delegate { + + override fun produce() = "${delegate.produce()} and EnhancedProducer" +} + +interface MessageService { + + fun processMessage(message: String): String +} + +class MessageServiceImpl : MessageService { + override fun processMessage(message: String): String { + return "MessageServiceImpl: $message" + } +} + +interface UserService { + + fun processUser(userId: String): String +} + +class UserServiceImpl : UserService { + + override fun processUser(userId: String): String { + return "UserServiceImpl: $userId" + } +} + +class CompositeService : UserService by UserServiceImpl(), MessageService by MessageServiceImpl() + +interface Service { + + val seed: Int + + fun serve(action: (Int) -> Unit) +} + +class ServiceImpl : Service { + + override val seed = 1 + + override fun serve(action: (Int) -> Unit) { + action(seed) + } +} + +class ServiceDecorator : Service by ServiceImpl() { + override val seed = 2 +} \ No newline at end of file diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegationTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegationTest.kt new file mode 100644 index 0000000000..e65032acd4 --- /dev/null +++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegationTest.kt @@ -0,0 +1,28 @@ +package com.baeldung.kotlin.delegates + +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test + +class InterfaceDelegationTest { + + @Test + fun `when delegated implementation is used then it works as expected`() { + val producer = EnhancedProducer(ProducerImpl()) + assertThat(producer.produce()).isEqualTo("ProducerImpl and EnhancedProducer") + } + + @Test + fun `when composite delegation is used then it works as expected`() { + val service = CompositeService() + assertThat(service.processMessage("message")).isEqualTo("MessageServiceImpl: message") + assertThat(service.processUser("user")).isEqualTo("UserServiceImpl: user") + } + + @Test + fun `when decoration is used then delegate knows nothing about it`() { + val service = ServiceDecorator() + service.serve { + assertThat(it).isEqualTo(1) + } + } +} \ No newline at end of file diff --git a/core-kotlin/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt new file mode 100644 index 0000000000..a9ddc99992 --- /dev/null +++ b/core-kotlin/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt @@ -0,0 +1,99 @@ +package com.baeldung.lambda + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class SplittingTest { + private val evenList = listOf(0, "a", 1, "b", 2, "c"); + + private val unevenList = listOf(0, "a", 1, "b", 2, "c", 3); + + private fun verifyList(resultList: List>) { + assertEquals("[[0, a], [1, b], [2, c]]", resultList.toString()) + } + + private fun verifyPartialList(resultList: List>) { + assertEquals("[[0, a], [1, b], [2, c], [3]]", resultList.toString()) + } + + @Test + fun whenChunked_thenListIsSplit() { + val resultList = evenList.chunked(2) + verifyList(resultList) + } + + @Test + fun whenUnevenChunked_thenListIsSplit() { + val resultList = unevenList.chunked(2) + verifyPartialList(resultList) + } + + @Test + fun whenWindowed_thenListIsSplit() { + val resultList = evenList.windowed(2, 2) + verifyList(resultList) + } + + @Test + fun whenUnevenPartialWindowed_thenListIsSplit() { + val resultList = unevenList.windowed(2, 2, partialWindows = true) + verifyPartialList(resultList) + } + + @Test + fun whenUnevenWindowed_thenListIsSplit() { + val resultList = unevenList.windowed(2, 2, partialWindows = false) + verifyList(resultList) + } + + @Test + fun whenGroupByWithAscendingNumbers_thenListIsSplit() { + val numberList = listOf(1, 2, 3, 4, 5, 6); + val resultList = numberList.groupBy { (it + 1) / 2 } + assertEquals("[[1, 2], [3, 4], [5, 6]]", resultList.values.toString()) + assertEquals("[1, 2, 3]", resultList.keys.toString()) + } + + @Test + fun whenGroupByWithAscendingNumbersUneven_thenListIsSplit() { + val numberList = listOf(1, 2, 3, 4, 5, 6, 7); + val resultList = numberList.groupBy { (it + 1) / 2 }.values + assertEquals("[[1, 2], [3, 4], [5, 6], [7]]", resultList.toString()) + } + + @Test + fun whenGroupByWithRandomNumbers_thenListIsSplitInWrongWay() { + val numberList = listOf(1, 3, 8, 20, 23, 30); + val resultList = numberList.groupBy { (it + 1) / 2 } + assertEquals("[[1], [3], [8], [20], [23], [30]]", resultList.values.toString()) + assertEquals("[1, 2, 4, 10, 12, 15]", resultList.keys.toString()) + } + + @Test + fun whenWithIndexGroupBy_thenListIsSplit() { + val resultList = evenList.withIndex() + .groupBy { it.index / 2 } + .map { it.value.map { it.value } } + verifyList(resultList) + } + + @Test + fun whenWithIndexGroupByUneven_thenListIsSplit() { + val resultList = unevenList.withIndex() + .groupBy { it.index / 2 } + .map { it.value.map { it.value } } + verifyPartialList(resultList) + } + + @Test + fun whenFoldIndexed_thenListIsSplit() { + val resultList = evenList.foldIndexed(ArrayList>(evenList.size / 2)) { index, acc, item -> + if (index % 2 == 0) { + acc.add(ArrayList(2)) + } + acc.last().add(item) + acc + } + verifyList(resultList) + } +} \ No newline at end of file diff --git a/guava-modules/pom.xml b/guava-modules/pom.xml new file mode 100644 index 0000000000..fed9e446f7 --- /dev/null +++ b/guava-modules/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + guava-modules + guava-modules + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + guava-18 + guava-19 + guava-21 + + + diff --git a/guice/README.md b/guice/README.md index d1bd1ff883..77c788c363 100644 --- a/guice/README.md +++ b/guice/README.md @@ -2,3 +2,4 @@ ### Relevant Articles - [Guide to Google Guice](http://www.baeldung.com/guice) +- [Guice vs Spring – Dependency Injection](https://www.baeldung.com/guice-spring-dependency-injection) diff --git a/httpclient/README.md b/httpclient/README.md index 93e0f3c9e1..7c5122c5b8 100644 --- a/httpclient/README.md +++ b/httpclient/README.md @@ -14,11 +14,11 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Unshorten URLs with HttpClient](http://www.baeldung.com/unshorten-url-httpclient) - [HttpClient with SSL](http://www.baeldung.com/httpclient-ssl) - [HttpClient 4 – Follow Redirects for POST](http://www.baeldung.com/httpclient-redirect-on-http-post) -- [HttpClient – Set Custom Header](http://www.baeldung.com/httpclient-custom-http-header) +- [Custom HTTP Header with the HttpClient](http://www.baeldung.com/httpclient-custom-http-header) - [HttpClient Basic Authentication](http://www.baeldung.com/httpclient-4-basic-authentication) - [Multipart Upload with HttpClient 4](http://www.baeldung.com/httpclient-multipart-upload) - [HttpAsyncClient Tutorial](http://www.baeldung.com/httpasyncclient-tutorial) - [HttpClient 4 Tutorial](http://www.baeldung.com/httpclient-guide) - [Advanced HttpClient Configuration](http://www.baeldung.com/httpclient-advanced-config) - [HttpClient 4 – Do Not Follow Redirects](http://www.baeldung.com/httpclient-stop-follow-redirect) -- [HttpClient 4 – Setting a Custom User-Agent](http://www.baeldung.com/httpclient-user-agent-header) +- [Custom User-Agent in HttpClient 4](http://www.baeldung.com/httpclient-user-agent-header) diff --git a/jackson/README.md b/jackson/README.md index e201a06727..25194c7255 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -10,14 +10,14 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Jackson – Unmarshall to Collection/Array](http://www.baeldung.com/jackson-collection-array) - [Jackson Unmarshalling json with Unknown Properties](http://www.baeldung.com/jackson-deserialize-json-unknown-properties) - [Jackson – Custom Serializer](http://www.baeldung.com/jackson-custom-serialization) -- [Jackson – Custom Deserializer](http://www.baeldung.com/jackson-deserialization) +- [Getting Started with Custom Deserialization in Jackson](http://www.baeldung.com/jackson-deserialization) - [Jackson Exceptions – Problems and Solutions](http://www.baeldung.com/jackson-exception) - [Jackson Date](http://www.baeldung.com/jackson-serialize-dates) - [Jackson – Bidirectional Relationships](http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion) - [Jackson JSON Tutorial](http://www.baeldung.com/jackson) - [Jackson – Working with Maps and nulls](http://www.baeldung.com/jackson-map-null-values-or-null-key) - [Jackson – Decide What Fields Get Serialized/Deserializaed](http://www.baeldung.com/jackson-field-serializable-deserializable-or-not) -- [A Guide to Jackson Annotations](http://www.baeldung.com/jackson-annotations) +- [Jackson Annotation Examples](http://www.baeldung.com/jackson-annotations) - [Working with Tree Model Nodes in Jackson](http://www.baeldung.com/jackson-json-node-tree-model) - [Jackson vs Gson](http://www.baeldung.com/jackson-vs-gson) - [Intro to the Jackson ObjectMapper](http://www.baeldung.com/jackson-object-mapper-tutorial) @@ -25,7 +25,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [More Jackson Annotations](http://www.baeldung.com/jackson-advanced-annotations) - [Inheritance with Jackson](http://www.baeldung.com/jackson-inheritance) - [Guide to @JsonFormat in Jackson](http://www.baeldung.com/jackson-jsonformat) -- [A Guide to Optional with Jackson](http://www.baeldung.com/jackson-optional) +- [Using Optional with Jackson](http://www.baeldung.com/jackson-optional) - [Map Serialization and Deserialization with Jackson](http://www.baeldung.com/jackson-map) - [Jackson Streaming API](http://www.baeldung.com/jackson-streaming-api) - [Jackson – JsonMappingException (No serializer found for class)](http://www.baeldung.com/jackson-jsonmappingexception) diff --git a/java-streams-2/pom.xml b/java-streams-2/pom.xml new file mode 100644 index 0000000000..cd89a1a80f --- /dev/null +++ b/java-streams-2/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + com.baeldung.javastreams2 + javastreams2 + 1.0 + jar + + + org.openjdk.jmh + jmh-core + 1.21 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.21 + + + junit + junit + 4.12 + test + jar + + + org.assertj + assertj-core + 3.11.1 + test + + + Stream Reduce + + UTF-8 + 1.8 + 1.8 + + \ No newline at end of file diff --git a/java-streams-2/src/main/java/com/baeldung/reduce/application/Application.java b/java-streams-2/src/main/java/com/baeldung/reduce/application/Application.java new file mode 100644 index 0000000000..79c557524d --- /dev/null +++ b/java-streams-2/src/main/java/com/baeldung/reduce/application/Application.java @@ -0,0 +1,39 @@ +package com.baeldung.reduce.application; + +import com.baeldung.reduce.entities.User; +import com.baeldung.reduce.utilities.NumberUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Application { + + public static void main(String[] args) { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + int result1 = numbers.stream().reduce(0, (subtotal, element) -> subtotal + element); + System.out.println(result1); + + int result2 = numbers.stream().reduce(0, Integer::sum); + System.out.println(result2); + + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result3 = letters.stream().reduce("", (partialString, element) -> partialString + element); + System.out.println(result3); + + String result4 = letters.stream().reduce("", String::concat); + System.out.println(result4); + + String result5 = letters.stream().reduce("", (partialString, element) -> partialString.toUpperCase() + element.toUpperCase()); + System.out.println(result5); + + List users = Arrays.asList(new User("John", 30), new User("Julie", 35)); + int result6 = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + System.out.println(result6); + + String result7 = letters.parallelStream().reduce("", String::concat); + System.out.println(result7); + + int result8 = users.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + System.out.println(result8); + } +} diff --git a/java-streams-2/src/main/java/com/baeldung/reduce/benchmarks/JMHStreamReduceBenchMark.java b/java-streams-2/src/main/java/com/baeldung/reduce/benchmarks/JMHStreamReduceBenchMark.java new file mode 100644 index 0000000000..af4a9276a9 --- /dev/null +++ b/java-streams-2/src/main/java/com/baeldung/reduce/benchmarks/JMHStreamReduceBenchMark.java @@ -0,0 +1,52 @@ +package com.baeldung.reduce.benchmarks; + +import com.baeldung.reduce.entities.User; +import java.util.ArrayList; +import java.util.List; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +public class JMHStreamReduceBenchMark { + + private final List userList = createUsers(); + + public static void main(String[] args) throws RunnerException { + + Options options = new OptionsBuilder() + .include(JMHStreamReduceBenchMark.class.getSimpleName()).threads(1) + .forks(1).shouldFailOnError(true).shouldDoGC(true) + .jvmArgs("-server").build(); + new Runner(options).run(); + } + + private List createUsers() { + List users = new ArrayList<>(); + for (int i = 0; i <= 1000000; i++) { + users.add(new User("John" + i, i)); + } + return users; + } + + @Benchmark + public Integer executeReduceOnParallelizedStream() { + return this.userList + .parallelStream() + .reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + } + + @Benchmark + public Integer executeReduceOnSequentialStream() { + return this.userList + .stream() + .reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + } +} diff --git a/java-streams-2/src/main/java/com/baeldung/reduce/entities/User.java b/java-streams-2/src/main/java/com/baeldung/reduce/entities/User.java new file mode 100644 index 0000000000..a17c6a02b6 --- /dev/null +++ b/java-streams-2/src/main/java/com/baeldung/reduce/entities/User.java @@ -0,0 +1,25 @@ +package com.baeldung.reduce.entities; + +public class User { + + private final String name; + private final int age; + + public User(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + @Override + public String toString() { + return "User{" + "name=" + name + ", age=" + age + '}'; + } +} diff --git a/java-streams-2/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java b/java-streams-2/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java new file mode 100644 index 0000000000..a7a4b8df29 --- /dev/null +++ b/java-streams-2/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java @@ -0,0 +1,52 @@ +package com.baeldung.reduce.utilities; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.logging.Level; +import java.util.logging.Logger; + +public abstract class NumberUtils { + + private static final Logger LOGGER = Logger.getLogger(NumberUtils.class.getName()); + + public static int divideListElements(List values, Integer divider) { + return values.stream() + .reduce(0, (a, b) -> { + try { + return a / divider + b / divider; + } catch (ArithmeticException e) { + LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero"); + } + return 0; + }); + } + + public static int divideListElementsWithExtractedTryCatchBlock(List values, int divider) { + return values.stream().reduce(0, (a, b) -> divide(a, divider) + divide(b, divider)); + } + + public static int divideListElementsWithApplyFunctionMethod(List values, int divider) { + BiFunction division = (a, b) -> a / b; + return values.stream().reduce(0, (a, b) -> applyFunction(division, a, divider) + applyFunction(division, b, divider)); + } + + private static int divide(int value, int factor) { + int result = 0; + try { + result = value / factor; + } catch (ArithmeticException e) { + LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero"); + } + return result; + } + + private static int applyFunction(BiFunction function, int a, int b) { + try { + return function.apply(a, b); + } + catch(Exception e) { + LOGGER.log(Level.INFO, "Exception thrown!"); + } + return 0; + } +} diff --git a/java-streams-2/src/test/java/com/baeldung/reduce/tests/StreamReduceUnitTest.java b/java-streams-2/src/test/java/com/baeldung/reduce/tests/StreamReduceUnitTest.java new file mode 100644 index 0000000000..564d614017 --- /dev/null +++ b/java-streams-2/src/test/java/com/baeldung/reduce/tests/StreamReduceUnitTest.java @@ -0,0 +1,79 @@ +package com.baeldung.reduce.tests; + +import com.baeldung.reduce.entities.User; +import com.baeldung.reduce.utilities.NumberUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class StreamReduceUnitTest { + + @Test + public void givenIntegerList_whenReduceWithSumAccumulatorLambda_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + int result = numbers.stream().reduce(0, (subtotal, element) -> subtotal + element); + assertThat(result).isEqualTo(21); + } + + @Test + public void givenIntegerList_whenReduceWithSumAccumulatorMethodReference_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + int result = numbers.stream().reduce(0, Integer::sum); + assertThat(result).isEqualTo(21); + } + + @Test + public void givenStringList_whenReduceWithConcatenatorAccumulatorLambda_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result = letters.stream().reduce("", (partialString, element) -> partialString + element); + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenStringList_whenReduceWithConcatenatorAccumulatorMethodReference_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result = letters.stream().reduce("", String::concat); + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenStringList_whenReduceWithUppercaseConcatenatorAccumulator_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result = letters.stream().reduce("", (partialString, element) -> partialString.toUpperCase() + element.toUpperCase()); + assertThat(result).isEqualTo("ABCDE"); + } + + @Test + public void givenUserList_whenReduceWithAgeAccumulatorAndSumCombiner_thenCorrect() { + List users = Arrays.asList(new User("John", 30), new User("Julie", 35)); + int result = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + assertThat(result).isEqualTo(65); + } + + @Test + public void givenStringList_whenReduceWithParallelStream_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result = letters.parallelStream().reduce("", String::concat); + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElements_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + assertThat(NumberUtils.divideListElements(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlock_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenStream_whneCalleddivideListElementsWithApplyFunctionMethod_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + assertThat(NumberUtils.divideListElementsWithApplyFunctionMethod(numbers, 1)).isEqualTo(21); + } +} diff --git a/java-streams/README.md b/java-streams/README.md index 15ea1c742a..b931c0d7d9 100644 --- a/java-streams/README.md +++ b/java-streams/README.md @@ -3,7 +3,7 @@ ## Java Streams Cookbooks and Examples ### Relevant Articles: -- [Java 8 Streams Advanced](http://www.baeldung.com/java-8-streams) +- [The Java 8 Stream API Tutorial](http://www.baeldung.com/java-8-streams) - [Introduction to Java 8 Streams](http://www.baeldung.com/java-8-streams-introduction) - [Java 8 and Infinite Streams](http://www.baeldung.com/java-inifinite-streams) - [Java 8 Stream findFirst() vs. findAny()](http://www.baeldung.com/java-stream-findfirst-vs-findany) diff --git a/java-strings/README.md b/java-strings/README.md index 1ab5e098f6..b342f53918 100644 --- a/java-strings/README.md +++ b/java-strings/README.md @@ -22,7 +22,7 @@ - [Check if a String is a Palindrome](http://www.baeldung.com/java-palindrome) - [Comparing Strings in Java](http://www.baeldung.com/java-compare-strings) - [Check If a String Is Numeric in Java](http://www.baeldung.com/java-check-string-number) -- [Why Use char[] Array Over a String for Storing Passwords in Java?](http://www.baeldung.com/java-storing-passwords) +- [Use char[] Array Over a String for Manipulating Passwords in Java?](http://www.baeldung.com/java-storing-passwords) - [Convert a String to Title Case](http://www.baeldung.com/java-string-title-case) - [Compact Strings in Java 9](http://www.baeldung.com/java-9-compact-string) - [Java Check a String for Lowercase/Uppercase Letter, Special Character and Digit](https://www.baeldung.com/java-lowercase-uppercase-special-character-digit-regex) @@ -53,3 +53,4 @@ - [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) +- [Common String Operations in Java](https://www.baeldung.com/java-string-operations) diff --git a/jhipster/README.md b/jhipster/README.md index 91ba54bf60..289bfac754 100644 --- a/jhipster/README.md +++ b/jhipster/README.md @@ -3,3 +3,4 @@ - [JHipster with a Microservice Architecture](http://www.baeldung.com/jhipster-microservices) - [Intro to JHipster](http://www.baeldung.com/jhipster) - [Building a Basic UAA-Secured JHipster Microservice](https://www.baeldung.com/jhipster-uaa-secured-micro-service) +- [Creating New Roles and Authorities in JHipster](https://www.baeldung.com/jhipster-new-roles) diff --git a/jooby/README.md b/jooby/README.md index 032e595354..aa867b2c56 100644 --- a/jooby/README.md +++ b/jooby/README.md @@ -1,3 +1,3 @@ ## Relevant articles: -- [Introduction to Jooby Project](http://www.baeldung.com/jooby) +- [Introduction to Jooby](http://www.baeldung.com/jooby) diff --git a/jsf/README.md b/jsf/README.md index 6e0891182d..d96c1eb8e3 100644 --- a/jsf/README.md +++ b/jsf/README.md @@ -1,5 +1,5 @@ ### Relevant Articles: -- [Introduction to JSF Expression Language 3.0](http://www.baeldung.com/jsf-expression-language-el-3) +- [Guide to JSF Expression Language 3.0](http://www.baeldung.com/jsf-expression-language-el-3) - [Introduction to JSF EL 2](http://www.baeldung.com/intro-to-jsf-expression-language) - [JavaServer Faces (JSF) with Spring](http://www.baeldung.com/spring-jsf) - [Introduction to Primefaces](http://www.baeldung.com/jsf-primefaces) diff --git a/json/README.md b/json/README.md index 2e253a4ae9..c0ca4b00ef 100644 --- a/json/README.md +++ b/json/README.md @@ -11,3 +11,5 @@ - [Overview of JSON Pointer](https://www.baeldung.com/json-pointer) - [Introduction to the JSON Binding API (JSR 367) in Java](http://www.baeldung.com/java-json-binding-api) - [Get a Value by Key in a JSONArray](https://www.baeldung.com/java-jsonarray-get-value-by-key) +- [Iterating Over an Instance of org.json.JSONObject](https://www.baeldung.com/jsonobject-iteration) +- [Testing Web APIs with Postman Collections](https://www.baeldung.com/postman-testing-collections) diff --git a/libraries/README.md b/libraries/README.md index 378317778e..57f22631f1 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -66,6 +66,7 @@ - [Implementing a FTP-Client in Java](http://www.baeldung.com/java-ftp-client) - [Introduction to Functional Java](https://www.baeldung.com/java-functional-library) - [Intro to Derive4J](https://www.baeldung.com/derive4j) +- [A Guide to the Reflections Library](https://www.baeldung.com/reflections-library) 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/logging-modules/pom.xml b/logging-modules/pom.xml new file mode 100644 index 0000000000..a303e50ff1 --- /dev/null +++ b/logging-modules/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + logging-modules + logging-modules + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + log4j + log4j2 + logback + log-mdc + + + diff --git a/maven/README.md b/maven/README.md index 1c0e50f95a..1352a2a10f 100644 --- a/maven/README.md +++ b/maven/README.md @@ -14,3 +14,4 @@ - [Apache Maven Tutorial](https://www.baeldung.com/maven) - [Use the Latest Version of a Dependency in Maven](https://www.baeldung.com/maven-dependency-latest-version) - [Multi-Module Project with Maven](https://www.baeldung.com/maven-multi-module) +- [Maven Enforcer Plugin](https://www.baeldung.com/maven-enforcer-plugin) diff --git a/maven/compiler-plugin-java-9/pom.xml b/maven/compiler-plugin-java-9/pom.xml new file mode 100644 index 0000000000..5303cee82e --- /dev/null +++ b/maven/compiler-plugin-java-9/pom.xml @@ -0,0 +1,22 @@ + + 4.0.0 + com.baeldung + compiler-plugin-java-9 + 0.0.1-SNAPSHOT + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 9 + 9 + + + + + \ No newline at end of file diff --git a/maven/compiler-plugin-java-9/src/main/java/com/baeldung/maven/java9/MavenCompilerPlugin.java b/maven/compiler-plugin-java-9/src/main/java/com/baeldung/maven/java9/MavenCompilerPlugin.java new file mode 100644 index 0000000000..b460d6e38c --- /dev/null +++ b/maven/compiler-plugin-java-9/src/main/java/com/baeldung/maven/java9/MavenCompilerPlugin.java @@ -0,0 +1,9 @@ +package com.baeldung.maven.java9; + +import static javax.xml.XMLConstants.XML_NS_PREFIX; + +public class MavenCompilerPlugin { + public static void main(String[] args) { + System.out.println("The XML namespace prefix is: " + XML_NS_PREFIX); + } +} diff --git a/maven/compiler-plugin-java-9/src/main/java/module-info.java b/maven/compiler-plugin-java-9/src/main/java/module-info.java new file mode 100644 index 0000000000..afc1d45e71 --- /dev/null +++ b/maven/compiler-plugin-java-9/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.maven.java9 { + requires java.xml; +} \ No newline at end of file diff --git a/parent-spring-5/pom.xml b/parent-spring-5/pom.xml index 5d7a3b66b3..3178682d34 100644 --- a/parent-spring-5/pom.xml +++ b/parent-spring-5/pom.xml @@ -29,10 +29,10 @@ - 5.1.2.RELEASE + 5.1.4.RELEASE 5.0.2 2.9.6 - 5.1.2.RELEASE + 5.1.4.RELEASE \ No newline at end of file diff --git a/patterns/design-patterns-2/pom.xml b/patterns/design-patterns-2/pom.xml new file mode 100644 index 0000000000..2a0213065b --- /dev/null +++ b/patterns/design-patterns-2/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + design-patterns-2 + 1.0 + design-patterns-2 + jar + + + com.baeldung + patterns + 1.0.0-SNAPSHOT + .. + + + + + + + UTF-8 + 1.8 + 1.8 + + diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/JmsRouter.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/JmsRouter.java new file mode 100644 index 0000000000..7d8215fead --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/JmsRouter.java @@ -0,0 +1,10 @@ +package com.baeldung.nullobject; + +public class JmsRouter implements Router { + + @Override + public void route(Message msg) { + System.out.println("Routing to a JMS queue. Msg: " + msg); + } + +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Message.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Message.java new file mode 100644 index 0000000000..9086b6d92d --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Message.java @@ -0,0 +1,24 @@ +package com.baeldung.nullobject; + +public class Message { + + private String body; + + private String priority; + + public Message(String body, String priority) { + this.body = body; + this.priority = priority; + } + + public String getPriority() { + return priority; + } + + @Override + public String toString() { + return "{body='" + body + '\'' + + ", priority='" + priority + '\'' + + '}'; + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/NullRouter.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/NullRouter.java new file mode 100644 index 0000000000..a0065a321d --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/NullRouter.java @@ -0,0 +1,10 @@ +package com.baeldung.nullobject; + +public class NullRouter implements Router { + + @Override + public void route(Message msg) { + // do nothing + } + +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Router.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Router.java new file mode 100644 index 0000000000..3e67de9558 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Router.java @@ -0,0 +1,7 @@ +package com.baeldung.nullobject; + +public interface Router { + + void route(Message msg); + +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/RouterFactory.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/RouterFactory.java new file mode 100644 index 0000000000..ba80834865 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/RouterFactory.java @@ -0,0 +1,23 @@ +package com.baeldung.nullobject; + +public class RouterFactory { + + public static Router getRouterForMessage(Message msg) { + + if (msg.getPriority() == null) { + return new NullRouter(); + } + + switch (msg.getPriority()) { + case "high": + return new SmsRouter(); + + case "medium": + return new JmsRouter(); + + default: + return new NullRouter(); + } + + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/RoutingHandler.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/RoutingHandler.java new file mode 100644 index 0000000000..282b066085 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/RoutingHandler.java @@ -0,0 +1,30 @@ +package com.baeldung.nullobject; + +import java.util.Arrays; +import java.util.List; + +public class RoutingHandler { + + public void handle(Iterable messages){ + for (Message msg : messages) { + Router router = RouterFactory.getRouterForMessage(msg); + router.route(msg); + } + } + + public static void main(String[] args) { + Message highPriorityMsg = new Message("Alert!", "high"); + Message mediumPriorityMsg = new Message("Warning!", "medium"); + Message lowPriorityMsg = new Message("Take a look!", "low"); + Message nullPriorityMsg = new Message("Take a look!", null); + + List messages = Arrays.asList(highPriorityMsg, + mediumPriorityMsg, + lowPriorityMsg, + nullPriorityMsg); + + RoutingHandler routingHandler = new RoutingHandler(); + routingHandler.handle(messages); + + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/SmsRouter.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/SmsRouter.java new file mode 100644 index 0000000000..3e8e2f15f3 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/SmsRouter.java @@ -0,0 +1,10 @@ +package com.baeldung.nullobject; + +public class SmsRouter implements Router { + + @Override + public void route(Message msg) { + System.out.println("Routing to a SMS gateway. Msg: " + msg); + } + +} diff --git a/patterns/pom.xml b/patterns/pom.xml index 3c3bb6d5ea..111e72b9ca 100644 --- a/patterns/pom.xml +++ b/patterns/pom.xml @@ -17,6 +17,7 @@ front-controller intercepting-filter design-patterns + design-patterns-2 solid diff --git a/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java index 749855ca3b..27aef8b82f 100644 --- a/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java +++ b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java @@ -1,5 +1,7 @@ package com.baeldung.jdbc; +import java.util.Objects; + public class Employee { private int id; private String name; @@ -48,4 +50,21 @@ public class Employee { this.position = position; } + @Override + public int hashCode() { + return Objects.hash(id, name, position, salary); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Employee other = (Employee) obj; + return id == other.id && Objects.equals(name, other.name) && Objects.equals(position, other.position) && Double.doubleToLongBits(salary) == Double.doubleToLongBits(other.salary); + } + } diff --git a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java new file mode 100644 index 0000000000..4e10f8bd43 --- /dev/null +++ b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java @@ -0,0 +1,359 @@ +package com.baeldung.jdbc; + +import static org.junit.Assert.assertEquals; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import junit.framework.Assert; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ResultSetLiveTest { + + private static final Logger logger = Logger.getLogger(ResultSetLiveTest.class); + + private final Employee expectedEmployee1 = new Employee(1, "John", 1000.0, "Developer"); + + private final Employee updatedEmployee1 = new Employee(1, "John", 1100.0, "Developer"); + + private final Employee expectedEmployee2 = new Employee(2, "Chris", 925.0, "DBA"); + + private final int rowCount = 2; + + private static Connection dbConnection; + + @BeforeClass + public static void setup() throws ClassNotFoundException, SQLException { + Class.forName("com.mysql.cj.jdbc.Driver"); + dbConnection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB?noAccessToProcedureBodies=true", "user1", "pass"); + String tableSql = "CREATE TABLE IF NOT EXISTS employees (emp_id int PRIMARY KEY AUTO_INCREMENT, name varchar(30), position varchar(30), salary double)"; + try (Statement stmt = dbConnection.createStatement()) { + stmt.execute(tableSql); + try (PreparedStatement pstmt = dbConnection.prepareStatement("INSERT INTO employees(name, position, salary) values ('John', 'Developer', 1000.0)")) { + pstmt.executeUpdate(); + } + } + } + + @Test + public void givenDbConnectionA_whenRetreiveByColumnNames_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees"); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + } + } + + assertEquals("Employee information retreived by column names.", expectedEmployee1, employee); + } + + @Test + public void givenDbConnectionB_whenRetreiveByColumnIds_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees"); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + Integer empId = rs.getInt(1); + String name = rs.getString(2); + String position = rs.getString(3); + Double salary = rs.getDouble(4); + employee = new Employee(empId, name, salary, position); + } + } + + assertEquals("Employee information retreived by column ids.", expectedEmployee1, employee); + } + + @Test + public void givenDbConnectionD_whenInsertRow_thenCorrect() throws SQLException { + int rowCount = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.moveToInsertRow(); + rs.updateString("name", "Chris"); + rs.updateString("position", "DBA"); + rs.updateDouble("salary", 925.0); + rs.insertRow(); + rs.moveToCurrentRow(); + rs.last(); + rowCount = rs.getRow(); + } + + assertEquals("Row Count after inserting a row", 2, rowCount); + } + + private Employee populateResultSet(ResultSet rs) throws SQLException { + Employee employee; + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + return employee; + } + + @Test + public void givenDbConnectionE_whenRowCount_thenCorrect() throws SQLException { + int numOfRows = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.last(); + numOfRows = rs.getRow(); + } + + assertEquals("Num of rows", rowCount, numOfRows); + } + + @Test + public void givenDbConnectionG_whenAbsoluteNavigation_thenCorrect() throws SQLException { + Employee secondEmployee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.absolute(2); + secondEmployee = populateResultSet(rs); + } + + assertEquals("Absolute navigation", expectedEmployee2, secondEmployee); + } + + @Test + public void givenDbConnectionH_whenLastNavigation_thenCorrect() throws SQLException { + Employee secondEmployee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.last(); + secondEmployee = populateResultSet(rs); + } + + assertEquals("Using Last", expectedEmployee2, secondEmployee); + } + + @Test + public void givenDbConnectionI_whenNavigation_thenCorrect() throws SQLException { + Employee firstEmployee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.beforeFirst(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.first(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + while (rs.previous()) { + Employee employee = populateResultSet(rs); + } + rs.afterLast(); + while (rs.previous()) { + Employee employee = populateResultSet(rs); + } + rs.last(); + while (rs.previous()) { + firstEmployee = populateResultSet(rs); + } + } + + assertEquals("Several Navigation Options", updatedEmployee1, firstEmployee); + } + + @Test + public void givenDbConnectionJ_whenClosedCursor_thenCorrect() throws SQLException { + Employee employee = null; + dbConnection.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); + try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT)) { + dbConnection.setAutoCommit(false); + ResultSet rs = pstmt.executeQuery("select * from employees"); + while (rs.next()) { + if (rs.getString("name") + .equalsIgnoreCase("john")) { + rs.updateString("position", "Senior Engineer"); + rs.updateRow(); + dbConnection.commit(); + employee = populateResultSet(rs); + } + } + rs.last(); + } + + assertEquals("Update using closed cursor", "Senior Engineer", employee.getPosition()); + } + + @Test + public void givenDbConnectionK_whenUpdate_thenCorrect() throws SQLException { + Employee employee = null; + dbConnection.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); + try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT)) { + dbConnection.setAutoCommit(false); + ResultSet rs = pstmt.executeQuery("select * from employees"); + while (rs.next()) { + if (rs.getString("name") + .equalsIgnoreCase("john")) { + rs.updateString("name", "John Doe"); + rs.updateRow(); + dbConnection.commit(); + employee = populateResultSet(rs); + } + } + rs.last(); + } + + assertEquals("Update using open cursor", "John Doe", employee.getName()); + } + + @Test + public void givenDbConnectionM_whenDelete_thenCorrect() throws SQLException { + int numOfRows = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.absolute(2); + rs.deleteRow(); + } + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.last(); + numOfRows = rs.getRow(); + } + assertEquals("Deleted row", 1, numOfRows); + } + + @Test + public void givenDbConnectionC_whenUpdate_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + + Assert.assertEquals(1100.0, rs.getDouble("salary")); + + rs.updateDouble("salary", 1200.0); + rs.updateRow(); + + Assert.assertEquals(1200.0, rs.getDouble("salary")); + + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + } + } + } + + @Test + public void givenDbConnectionC_whenUpdateByIndex_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + + Assert.assertEquals(1000.0, rs.getDouble(4)); + + rs.updateDouble(4, 1100.0); + rs.updateRow(); + Assert.assertEquals(1100.0, rs.getDouble(4)); + + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + } + } + } + + @Test + public void givenDbConnectionE_whenDBMetaInfo_thenCorrect() throws SQLException { + DatabaseMetaData dbmd = dbConnection.getMetaData(); + boolean supportsTypeForward = dbmd.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY); + boolean supportsTypeScrollSensitive = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE); + boolean supportsTypeScrollInSensitive = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE); + boolean supportsCloseCursorsAtCommit = dbmd.supportsResultSetHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); + boolean supportsHoldCursorsAtCommit = dbmd.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); + boolean concurrency4TypeFwdNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + boolean concurrency4TypeFwdNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); + boolean concurrency4TypeScrollInSensitiveNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); + boolean concurrency4TypeScrollInSensitiveNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + boolean concurrency4TypeScrollSensitiveNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); + boolean concurrency4TypeScrollSensitiveNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); + int rsHoldability = dbmd.getResultSetHoldability(); + + assertEquals("checking scroll sensitivity and concur updates : ", true, concurrency4TypeScrollInSensitiveNConcurUpdatable); + } + + @Test + public void givenDbConnectionF_whenRSMetaInfo_thenCorrect() throws SQLException { + int columnCount = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + ResultSetMetaData metaData = rs.getMetaData(); + columnCount = metaData.getColumnCount(); + for (int i = 1; i <= columnCount; i++) { + String catalogName = metaData.getCatalogName(i); + String className = metaData.getColumnClassName(i); + String label = metaData.getColumnLabel(i); + String name = metaData.getColumnName(i); + String typeName = metaData.getColumnTypeName(i); + Integer type = metaData.getColumnType(i); + String tableName = metaData.getTableName(i); + String schemaName = metaData.getSchemaName(i); + boolean isAutoIncrement = metaData.isAutoIncrement(i); + boolean isCaseSensitive = metaData.isCaseSensitive(i); + boolean isCurrency = metaData.isCurrency(i); + boolean isDefiniteWritable = metaData.isDefinitelyWritable(i); + boolean isReadOnly = metaData.isReadOnly(i); + boolean isSearchable = metaData.isSearchable(i); + boolean isReadable = metaData.isReadOnly(i); + boolean isSigned = metaData.isSigned(i); + boolean isWritable = metaData.isWritable(i); + int nullable = metaData.isNullable(i); + } + } + + assertEquals("column count", 4, columnCount); + } + + @Test + public void givenDbConnectionL_whenFetch_thenCorrect() throws SQLException { + PreparedStatement pstmt = null; + ResultSet rs = null; + List listOfEmployees = new ArrayList(); + try { + pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); + pstmt.setFetchSize(1); + rs = pstmt.executeQuery(); + rs.setFetchSize(1); + while (rs.next()) { + Employee employee = populateResultSet(rs); + listOfEmployees.add(employee); + } + } catch (Exception e) { + throw e; + } finally { + if (rs != null) + rs.close(); + if (pstmt != null) + pstmt.close(); + } + + assertEquals(2, listOfEmployees.size()); + } + + @AfterClass + public static void closeConnection() throws SQLException { + PreparedStatement deleteStmt = dbConnection.prepareStatement("drop table employees", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); + deleteStmt.execute(); + dbConnection.close(); + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate5/README.md b/persistence-modules/hibernate5/README.md index a4e95a9062..a37720a428 100644 --- a/persistence-modules/hibernate5/README.md +++ b/persistence-modules/hibernate5/README.md @@ -18,7 +18,7 @@ - [@JoinColumn Annotation Explained](https://www.baeldung.com/jpa-join-column) - [Hibernate 5 Naming Strategy Configuration](https://www.baeldung.com/hibernate-naming-strategy) - [Proxy in Hibernate load() Method](https://www.baeldung.com/hibernate-proxy-load-method) -- [Custom Types in Hibernate](https://www.baeldung.com/hibernate-custom-types) +- [Custom Types in Hibernate and the @Type Annotation](https://www.baeldung.com/hibernate-custom-types) - [Criteria API – An Example of IN Expressions](https://www.baeldung.com/jpa-criteria-api-in-expressions) - [Difference Between @JoinColumn and mappedBy](https://www.baeldung.com/jpa-joincolumn-vs-mappedby) - [Hibernate 5 Bootstrapping API](https://www.baeldung.com/hibernate-5-bootstrapping-api) @@ -30,3 +30,5 @@ - [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) +- [Hibernate Aggregate Functions](https://www.baeldung.com/hibernate-aggregate-functions) +- [Hibernate Query Plan Cache](https://www.baeldung.com/hibernate-query-plan-cache) diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml new file mode 100644 index 0000000000..47c733d8a7 --- /dev/null +++ b/persistence-modules/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + persistence-modules + persistence-modules + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + activejdbc + apache-cayenne + core-java-persistence + deltaspike + flyway + hbase + hibernate5 + hibernate-ogm + influxdb + java-cassandra + java-cockroachdb + java-jdbi + java-jpa + java-mongodb + jnosql + liquibase + orientdb + querydsl + redis + solr + spring-boot-h2/spring-boot-h2-database + spring-boot-persistence + spring-boot-persistence-mongodb + spring-data-cassandra + spring-data-cassandra-reactive + spring-data-couchbase-2 + spring-data-dynamodb + spring-data-eclipselink + spring-data-elasticsearch + spring-data-gemfire + spring-data-jpa + spring-data-keyvalue + spring-data-mongodb + spring-data-neo4j + spring-data-redis + spring-data-solr + spring-hibernate-3 + spring-hibernate-5 + spring-hibernate4 + spring-jpa + + diff --git a/persistence-modules/spring-boot-persistence/README.MD b/persistence-modules/spring-boot-persistence/README.MD index 6fe5e6f05f..f62ca57a19 100644 --- a/persistence-modules/spring-boot-persistence/README.MD +++ b/persistence-modules/spring-boot-persistence/README.MD @@ -2,7 +2,7 @@ - [Spring Boot with Multiple SQL Import Files](http://www.baeldung.com/spring-boot-sql-import-files) - [Configuring Separate Spring DataSource for Tests](http://www.baeldung.com/spring-testing-separate-data-source) -- [Quick Guide on data.sql and schema.sql Files in Spring Boot](http://www.baeldung.com/spring-boot-data-sql-and-schema-sql) +- [Quick Guide on Loading Initial Data with Spring Boot](http://www.baeldung.com/spring-boot-data-sql-and-schema-sql) - [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) diff --git a/persistence-modules/spring-data-couchbase-2/README.md b/persistence-modules/spring-data-couchbase-2/README.md index 2e56b25fef..2b6a1faddf 100644 --- a/persistence-modules/spring-data-couchbase-2/README.md +++ b/persistence-modules/spring-data-couchbase-2/README.md @@ -1,7 +1,7 @@ ## Spring Data Couchbase Tutorial Project ### Relevant Articles: -- [Spring Data Couchbase](http://www.baeldung.com/spring-data-couchbase) +- [Intro to Spring Data Couchbase](http://www.baeldung.com/spring-data-couchbase) - [Entity Validation, Query Consistency, and Optimistic Locking in Spring Data Couchbase](http://www.baeldung.com/entity-validation-locking-and-query-consistency-in-spring-data-couchbase) - [Multiple Buckets and Spatial View Queries in Spring Data Couchbase](http://www.baeldung.com/spring-data-couchbase-buckets-and-spatial-view-queries) diff --git a/persistence-modules/spring-data-jpa/README.md b/persistence-modules/spring-data-jpa/README.md index 739031ff5e..9512ad336d 100644 --- a/persistence-modules/spring-data-jpa/README.md +++ b/persistence-modules/spring-data-jpa/README.md @@ -20,6 +20,8 @@ - [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) +- [DB Integration Tests with Spring Boot and Testcontainers](https://www.baeldung.com/spring-boot-testcontainers-integration-test) +- [Spring Data JPA @Modifying Annotation](https://www.baeldung.com/spring-data-jpa-modifying-annotation) ### Eclipse Config After importing the project into Eclipse, you may see the following error: diff --git a/persistence-modules/spring-hibernate-5/README.md b/persistence-modules/spring-hibernate-5/README.md index 5e287919f1..c48e58fcca 100644 --- a/persistence-modules/spring-hibernate-5/README.md +++ b/persistence-modules/spring-hibernate-5/README.md @@ -2,4 +2,4 @@ - [Hibernate Many to Many Annotation Tutorial](http://www.baeldung.com/hibernate-many-to-many) - [Programmatic Transactions in the Spring TestContext Framework](http://www.baeldung.com/spring-test-programmatic-transactions) -- [Hibernate Criteria Queries](http://www.baeldung.com/hibernate-criteria-queries) +- [JPA Criteria Queries](http://www.baeldung.com/hibernate-criteria-queries) diff --git a/persistence-modules/spring-hibernate4/README.md b/persistence-modules/spring-hibernate4/README.md index 57a341ed45..f2553ad229 100644 --- a/persistence-modules/spring-hibernate4/README.md +++ b/persistence-modules/spring-hibernate4/README.md @@ -3,8 +3,8 @@ ## Spring with Hibernate 4 Example Project ### Relevant Articles: -- [Hibernate 4 with Spring](http://www.baeldung.com/hibernate-4-spring) -- [The DAO with Spring 3 and Hibernate](http://www.baeldung.com/persistence-layer-with-spring-and-hibernate) +- [Guide to Hibernate 4 with Spring](http://www.baeldung.com/hibernate-4-spring) +- [The DAO with Spring and Hibernate](http://www.baeldung.com/persistence-layer-with-spring-and-hibernate) - [Hibernate Pagination](http://www.baeldung.com/hibernate-pagination) - [Sorting with Hibernate](http://www.baeldung.com/hibernate-sort) - [Stored Procedures with Hibernate](http://www.baeldung.com/stored-procedures-with-hibernate-tutorial) diff --git a/pom.xml b/pom.xml index 81f55e3cbf..3e739daf22 100644 --- a/pom.xml +++ b/pom.xml @@ -371,8 +371,7 @@ bootique - cas/cas-secured-app - cas/cas-server + cas cdi checker-plugin core-groovy @@ -422,9 +421,7 @@ gson guava guava-collections - guava-modules/guava-18 - guava-modules/guava-19 - guava-modules/guava-21 + guava-modules guice @@ -475,16 +472,13 @@ kotlin-libraries - libraries + libraries libraries-data libraries-apache-commons libraries-security libraries-server linkrest - logging-modules/log4j - logging-modules/log4j2 - logging-modules/logback - logging-modules/log-mdc + logging-modules lombok lucene @@ -515,45 +509,7 @@ protobuffer - persistence-modules/activejdbc - persistence-modules/apache-cayenne - persistence-modules/core-java-persistence - persistence-modules/deltaspike - persistence-modules/flyway - persistence-modules/hbase - persistence-modules/hibernate5 - persistence-modules/hibernate-ogm - persistence-modules/influxdb - persistence-modules/java-cassandra - persistence-modules/java-cockroachdb - persistence-modules/java-jdbi - persistence-modules/java-jpa - persistence-modules/jnosql - persistence-modules/liquibase - persistence-modules/orientdb - persistence-modules/querydsl - persistence-modules/redis - persistence-modules/solr - persistence-modules/spring-boot-h2/spring-boot-h2-database - persistence-modules/spring-boot-persistence - persistence-modules/spring-boot-persistence-mongodb - persistence-modules/spring-data-cassandra - persistence-modules/spring-data-cassandra-reactive - persistence-modules/spring-data-couchbase-2 - persistence-modules/spring-data-dynamodb - persistence-modules/spring-data-eclipselink - persistence-modules/spring-data-elasticsearch - persistence-modules/spring-data-gemfire - persistence-modules/spring-data-jpa - persistence-modules/spring-data-keyvalue - persistence-modules/spring-data-mongodb - persistence-modules/spring-data-neo4j - persistence-modules/spring-data-redis - persistence-modules/spring-data-solr - persistence-modules/spring-hibernate-3 - persistence-modules/spring-hibernate-5 - persistence-modules/spring-hibernate4 - persistence-modules/spring-jpa + persistence-modules rabbitmq @@ -563,9 +519,7 @@ resteasy restx - rule-engines/easy-rules - rule-engines/openl-tablets - rule-engines/rulebook + rule-engines rsocket rxjava rxjava-2 @@ -721,13 +675,7 @@ spring-security-angular/server spring-security-cache-control - spring-security-client/spring-security-jsp-authentication - spring-security-client/spring-security-jsp-authorize - spring-security-client/spring-security-jsp-config - spring-security-client/spring-security-mvc - spring-security-client/spring-security-thymeleaf-authentication - spring-security-client/spring-security-thymeleaf-authorize - spring-security-client/spring-security-thymeleaf-config + spring-security-client spring-security-core spring-security-mvc-boot @@ -773,24 +721,7 @@ structurizr struts-2 - testing-modules/gatling - testing-modules/groovy-spock - testing-modules/junit-5 - testing-modules/junit5-migration - testing-modules/load-testing-comparison - testing-modules/mockito - testing-modules/mockito-2 - testing-modules/mocks - testing-modules/mockserver - testing-modules/parallel-tests-junit - testing-modules/rest-assured - testing-modules/rest-testing - - testing-modules/selenium-junit-testng - testing-modules/spring-testing - testing-modules/test-containers - testing-modules/testing - testing-modules/testng + testing-modules twilio Twitter4J @@ -849,8 +780,7 @@ spring-apache-camel spring-batch spring-bom - spring-boot-admin/spring-boot-admin-client - spring-boot-admin/spring-boot-admin-server + spring-boot-admin spring-boot-bootstrap spring-boot-bootstrap spring-boot-camel @@ -862,22 +792,18 @@ spring-boot-jasypt spring-boot-keycloak spring-boot-mvc - spring-boot-property-exp/property-exp-custom-config - spring-boot-property-exp/property-exp-default-config + spring-boot-property-exp spring-boot-vue spring-cloud spring-cloud/spring-cloud-archaius/basic-config spring-cloud/spring-cloud-archaius/extra-configs spring-cloud/spring-cloud-bootstrap/config - spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer - spring-cloud/spring-cloud-contract/spring-cloud-contract-producer + spring-cloud/spring-cloud-contract spring-cloud/spring-cloud-gateway spring-cloud/spring-cloud-kubernetes/demo-backend spring-cloud/spring-cloud-rest/spring-cloud-rest-config-server spring-cloud/spring-cloud-ribbon-client - spring-cloud/spring-cloud-security/auth-client - spring-cloud/spring-cloud-security/auth-resource - spring-cloud/spring-cloud-security/auth-server + spring-cloud/spring-cloud-security spring-cloud/spring-cloud-stream/spring-cloud-stream-rabbit spring-cloud/spring-cloud-task/springcloudtasksink spring-cloud/spring-cloud-zookeeper @@ -925,13 +851,7 @@ spring-security-acl spring-security-angular spring-security-cache-control - spring-security-client/spring-security-jsp-authentication - spring-security-client/spring-security-jsp-authorize - spring-security-client/spring-security-jsp-config - spring-security-client/spring-security-mvc - spring-security-client/spring-security-thymeleaf-authentication - spring-security-client/spring-security-thymeleaf-authorize - spring-security-client/spring-security-thymeleaf-config + spring-security-client spring-security-core spring-security-mvc-boot spring-security-mvc-custom @@ -941,14 +861,11 @@ spring-security-mvc-session spring-security-mvc-socket spring-security-rest - spring-security-sso/spring-security-sso-auth-server - spring-security-sso/spring-security-sso-ui - spring-security-sso/spring-security-sso-ui-2 + spring-security-sso spring-security-thymeleaf/spring-security-thymeleaf-authentication spring-security-thymeleaf/spring-security-thymeleaf-authorize spring-security-thymeleaf/spring-security-thymeleaf-config - spring-security-x509/spring-security-x509-basic-auth - spring-security-x509/spring-security-x509-client-auth + spring-security-x509 spring-session/spring-session-jdbc spring-sleuth spring-social-login @@ -1090,8 +1007,7 @@ bootique - cas/cas-secured-app - cas/cas-server + cas cdi checker-plugin core-groovy @@ -1140,9 +1056,7 @@ gson guava guava-collections - guava-modules/guava-18 - guava-modules/guava-19 - guava-modules/guava-21 + guava-modules guice @@ -1199,10 +1113,7 @@ libraries-security libraries-server linkrest - logging-modules/log4j - logging-modules/log4j2 - logging-modules/logback - logging-modules/log-mdc + logging-modules lombok lucene @@ -1233,46 +1144,8 @@ protobuffer - persistence-modules/activejdbc - persistence-modules/apache-cayenne - persistence-modules/core-java-persistence - persistence-modules/deltaspike - persistence-modules/flyway - persistence-modules/hbase - persistence-modules/hibernate5 - persistence-modules/hibernate-ogm - persistence-modules/influxdb - persistence-modules/java-cassandra - persistence-modules/java-cockroachdb - persistence-modules/java-jdbi - persistence-modules/java-jpa - persistence-modules/jnosql - persistence-modules/liquibase - persistence-modules/orientdb - persistence-modules/querydsl - persistence-modules/redis - persistence-modules/solr - persistence-modules/spring-boot-h2/spring-boot-h2-database - persistence-modules/spring-boot-persistence - persistence-modules/spring-boot-persistence-mongodb - persistence-modules/spring-data-cassandra - persistence-modules/spring-data-cassandra-reactive - persistence-modules/spring-data-couchbase-2 - persistence-modules/spring-data-dynamodb - persistence-modules/spring-data-eclipselink - persistence-modules/spring-data-elasticsearch - persistence-modules/spring-data-gemfire - persistence-modules/spring-data-jpa - persistence-modules/spring-data-keyvalue - persistence-modules/spring-data-mongodb - persistence-modules/spring-data-neo4j - persistence-modules/spring-data-redis - persistence-modules/spring-data-solr - persistence-modules/spring-hibernate-3 - persistence-modules/spring-hibernate-5 - persistence-modules/spring-hibernate4 - persistence-modules/spring-jpa - + persistence-modules + rabbitmq ratpack @@ -1281,9 +1154,7 @@ resteasy restx - rule-engines/easy-rules - rule-engines/openl-tablets - rule-engines/rulebook + rule-engines rsocket rxjava rxjava-2 @@ -1434,13 +1305,7 @@ spring-security-angular/server spring-security-cache-control - spring-security-client/spring-security-jsp-authentication - spring-security-client/spring-security-jsp-authorize - spring-security-client/spring-security-jsp-config - spring-security-client/spring-security-mvc - spring-security-client/spring-security-thymeleaf-authentication - spring-security-client/spring-security-thymeleaf-authorize - spring-security-client/spring-security-thymeleaf-config + spring-security-client spring-security-core spring-security-mvc-boot @@ -1485,24 +1350,7 @@ structurizr struts-2 - testing-modules/gatling - testing-modules/groovy-spock - testing-modules/junit-5 - testing-modules/junit5-migration - testing-modules/load-testing-comparison - testing-modules/mockito - testing-modules/mockito-2 - testing-modules/mocks - testing-modules/mockserver - testing-modules/parallel-tests-junit - testing-modules/rest-assured - testing-modules/rest-testing - - testing-modules/selenium-junit-testng - testing-modules/spring-testing - testing-modules/test-containers - testing-modules/testing - testing-modules/testng + testing-modules twilio Twitter4J diff --git a/ratpack/README.md b/ratpack/README.md index dded42fab6..14bc3f6c74 100644 --- a/ratpack/README.md +++ b/ratpack/README.md @@ -5,3 +5,4 @@ - [Ratpack Integration with Spring Boot](http://www.baeldung.com/ratpack-spring-boot) - [Ratpack with Hystrix](http://www.baeldung.com/ratpack-hystrix) - [Ratpack HTTP Client](https://www.baeldung.com/ratpack-http-client) +- [Ratpack with RxJava](https://www.baeldung.com/ratpack-rxjava) diff --git a/rule-engines/pom.xml b/rule-engines/pom.xml new file mode 100644 index 0000000000..2ce82ed22b --- /dev/null +++ b/rule-engines/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + rule-engines + rule-engines + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + easy-rules + openl-tablets + rulebook + + + diff --git a/software-security/sql-injection-samples/README.md b/software-security/sql-injection-samples/README.md new file mode 100644 index 0000000000..7a077074ac --- /dev/null +++ b/software-security/sql-injection-samples/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [SQL Injection and How to Prevent It?](https://www.baeldung.com/sql-injection) diff --git a/spark-java/README.md b/spark-java/README.md index 711607bd4e..5abe78263c 100644 --- a/spark-java/README.md +++ b/spark-java/README.md @@ -3,4 +3,4 @@ ## Spark Java Framework Tutorial Sample Project ### Relevant Articles -- [Intro to Spark Java Framework](http://www.baeldung.com/spark-framework-rest-api) +- [Building an API With the Spark Java Framework](http://www.baeldung.com/spark-framework-rest-api) diff --git a/spring-5-reactive/README.md b/spring-5-reactive/README.md index c39bb616f8..ef2f7d07eb 100644 --- a/spring-5-reactive/README.md +++ b/spring-5-reactive/README.md @@ -7,7 +7,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Introduction to the Functional Web Framework in Spring 5](http://www.baeldung.com/spring-5-functional-web) - [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient) -- [Exploring the Spring 5 MVC URL Matching Improvements](http://www.baeldung.com/spring-5-mvc-url-matching) +- [Exploring the Spring 5 WebFlux URL Matching](http://www.baeldung.com/spring-5-mvc-url-matching) - [Reactive WebSockets with Spring 5](http://www.baeldung.com/spring-5-reactive-websockets) - [Spring Webflux Filters](http://www.baeldung.com/spring-webflux-filters) - [How to Set a Header on a Response with Spring 5](http://www.baeldung.com/spring-response-header) diff --git a/spring-all/README.md b/spring-all/README.md index 0d78efdcf2..81dd435007 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -11,11 +11,11 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant articles: - [Guide to Spring @Autowired](http://www.baeldung.com/spring-autowire) -- [Properties with Spring](http://www.baeldung.com/properties-with-spring) - checkout the `org.baeldung.properties` package for all scenarios of properties injection and usage +- [Properties with Spring and Spring Boot](http://www.baeldung.com/properties-with-spring) - checkout the `org.baeldung.properties` package for all scenarios of properties injection and usage - [Spring Profiles](http://www.baeldung.com/spring-profiles) - [A Spring Custom Annotation for a Better DAO](http://www.baeldung.com/spring-annotation-bean-pre-processor) - [What's New in Spring 4.3?](http://www.baeldung.com/whats-new-in-spring-4-3) -- [Guide To Running Logic on Startup in Spring](http://www.baeldung.com/running-setup-logic-on-startup-in-spring) +- [Running Setup Data on Startup in Spring](http://www.baeldung.com/running-setup-logic-on-startup-in-spring) - [Quick Guide to Spring Controllers](http://www.baeldung.com/spring-controllers) - [Quick Guide to Spring Bean Scopes](http://www.baeldung.com/spring-bean-scopes) - [Introduction To Ehcache](http://www.baeldung.com/ehcache) @@ -28,7 +28,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Model, ModelMap, and ModelView in Spring MVC](http://www.baeldung.com/spring-mvc-model-model-map-model-view) - [A Guide To Caching in Spring](http://www.baeldung.com/spring-cache-tutorial) - [How To Do @Async in Spring](http://www.baeldung.com/spring-async) -- [Quick Guide to the Spring @Order Annotation](http://www.baeldung.com/spring-order) +- [@Order in Spring](http://www.baeldung.com/spring-order) - [Spring Web Contexts](http://www.baeldung.com/spring-web-contexts) - [Spring Cache – Creating a Custom KeyGenerator](http://www.baeldung.com/spring-cache-custom-keygenerator) - [Spring @Primary Annotation](http://www.baeldung.com/spring-primary) diff --git a/spring-all/pom.xml b/spring-all/pom.xml index 5872fbdac5..8c88efb970 100644 --- a/spring-all/pom.xml +++ b/spring-all/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-all 0.1-SNAPSHOT @@ -47,12 +47,16 @@ org.springframework spring-websocket - - + + org.springframework spring-messaging - - + + + javax.annotation + javax.annotation-api + ${annotation-api.version} + org.springframework @@ -227,13 +231,13 @@ - + org.baeldung.sample.App 5.0.6.RELEASE 1.2.0.RELEASE - + 1.3.2 5.2.5.Final diff --git a/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithJavaConfig.java b/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithJavaConfig.java index 08626bb4d2..6589143a94 100644 --- a/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithJavaConfig.java +++ b/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithJavaConfig.java @@ -7,6 +7,7 @@ import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; @Configuration @PropertySource("classpath:foo.properties") +@PropertySource("classpath:bar.properties") public class PropertiesWithJavaConfig { public PropertiesWithJavaConfig() { diff --git a/spring-all/src/main/resources/configForProperties.xml b/spring-all/src/main/resources/configForProperties.xml index 0f766665eb..459aea3ec6 100644 --- a/spring-all/src/main/resources/configForProperties.xml +++ b/spring-all/src/main/resources/configForProperties.xml @@ -7,7 +7,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd" > - + diff --git a/spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesJavaConfigIntegrationTest.java b/spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesJavaConfigIntegrationTest.java new file mode 100644 index 0000000000..9cb41c20f7 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesJavaConfigIntegrationTest.java @@ -0,0 +1,25 @@ +package org.baeldung.properties.multiple; + +import org.baeldung.properties.spring.PropertiesWithJavaConfig; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringJUnitConfig(PropertiesWithJavaConfig.class) +public class MultiplePropertiesJavaConfigIntegrationTest { + + @Value("${key.something}") + private String something; + + @Value("${key.something2}") + private String something2; + + + @Test + public void whenReadInjectedValues_thenGetCorrectValues() { + assertThat(something).isEqualTo("val"); + assertThat(something2).isEqualTo("val2"); + } +} diff --git a/spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesXmlConfigIntegrationTest.java b/spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesXmlConfigIntegrationTest.java new file mode 100644 index 0000000000..b4f81f3541 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesXmlConfigIntegrationTest.java @@ -0,0 +1,21 @@ +package org.baeldung.properties.multiple; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringJUnitConfig(locations = "classpath:configForProperties.xml") +public class MultiplePropertiesXmlConfigIntegrationTest { + + @Value("${key.something}") private String something; + + @Value("${key.something2}") private String something2; + + @Test + public void whenReadInjectedValues_thenGetCorrectValues() { + assertThat(something).isEqualTo("val"); + assertThat(something2).isEqualTo("val2"); + } +} diff --git a/spring-boot-bootstrap/README.md b/spring-boot-bootstrap/README.md index 2186aa8fec..70fcd90118 100644 --- a/spring-boot-bootstrap/README.md +++ b/spring-boot-bootstrap/README.md @@ -1,5 +1,5 @@ ### Relevant Articles: -- [Bootstrap a Simple Application using Spring Boot](http://www.baeldung.com/spring-boot-start) +- [Spring Boot Tutorial – Bootstrap a Simple Application](http://www.baeldung.com/spring-boot-start) - [Spring Boot Dependency Management with a Custom Parent](http://www.baeldung.com/spring-boot-dependency-management-custom-parent) - [Thin JARs with Spring Boot](http://www.baeldung.com/spring-boot-thin-jar) - [Deploying a Spring Boot Application to Cloud Foundry](https://www.baeldung.com/spring-boot-app-deploy-to-cloud-foundry) diff --git a/spring-boot-libraries/README.MD b/spring-boot-libraries/README.MD index cc32ce8355..f3706e0fa4 100644 --- a/spring-boot-libraries/README.MD +++ b/spring-boot-libraries/README.MD @@ -4,3 +4,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [Guide to ShedLock with Spring](https://www.baeldung.com/shedlock-spring) +- [A Guide to the Problem Spring Web Library](https://www.baeldung.com/problem-spring-web) diff --git a/spring-boot-mvc/README.md b/spring-boot-mvc/README.md index 0e1ac5a8ce..d5a39cdc9f 100644 --- a/spring-boot-mvc/README.md +++ b/spring-boot-mvc/README.md @@ -11,3 +11,4 @@ - [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) - [Conditionally Enable Scheduled Jobs in Spring](https://www.baeldung.com/spring-scheduled-enabled-conditionally) +- [Accessing Spring MVC Model Objects in JavaScript](https://www.baeldung.com/spring-mvc-model-objects-js) diff --git a/spring-boot-security/pom.xml b/spring-boot-security/pom.xml index aaa0fbf4c7..80f5d46f0d 100644 --- a/spring-boot-security/pom.xml +++ b/spring-boot-security/pom.xml @@ -8,10 +8,10 @@ jar - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 @@ -22,6 +22,12 @@ org.springframework.security.oauth spring-security-oauth2 + 2.3.3.RELEASE + + + org.springframework.security.oauth.boot + spring-security-oauth2-autoconfigure + 2.1.2.RELEASE org.springframework.boot diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java index 2ecad4ae35..7007c15596 100644 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java @@ -2,14 +2,13 @@ package com.baeldung.springbootsecurity.basic_auth; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; @SpringBootApplication(exclude = { SecurityAutoConfiguration.class // ,ManagementWebSecurityAutoConfiguration.class }, scanBasePackages = "com.baeldung.springbootsecurity.basic_auth") public class SpringBootSecurityApplication { - public static void main(String[] args) { SpringApplication.run(SpringBootSecurityApplication.class, args); } diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java index 993c573fb0..592ef5354d 100644 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java @@ -5,6 +5,8 @@ import org.springframework.security.config.annotation.authentication.builders.Au 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.factory.PasswordEncoderFactories; +import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity @@ -12,14 +14,15 @@ public class BasicAuthConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth + PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); + auth .inMemoryAuthentication() .withUser("user") - .password("password") + .password(encoder.encode("password")) .roles("USER") .and() .withUser("admin") - .password("admin") + .password(encoder.encode("admin")) .roles("USER", "ADMIN"); } diff --git a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java index 32c3fbdef4..94cf9f4148 100644 --- a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java +++ b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java @@ -1,12 +1,11 @@ package com.baeldung.springbootsecurity.basic_auth; -import com.baeldung.springbootsecurity.basic_auth.SpringBootSecurityApplication; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.context.embedded.LocalServerPort; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringRunner; @@ -18,7 +17,6 @@ import java.net.URL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; - @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT, classes = SpringBootSecurityApplication.class) public class BasicAuthConfigurationIntegrationTest { diff --git a/spring-cloud-data-flow/apache-spark-job/pom.xml b/spring-cloud-data-flow/apache-spark-job/pom.xml new file mode 100644 index 0000000000..390b7ebdc6 --- /dev/null +++ b/spring-cloud-data-flow/apache-spark-job/pom.xml @@ -0,0 +1,36 @@ + + + + spring-cloud-data-flow + com.baeldung + 0.0.1-SNAPSHOT + + 4.0.0 + + apache-spark-job + + + org.springframework.cloud + spring-cloud-task-core + 2.0.0.RELEASE + + + org.apache.spark + spark-core_2.10 + 1.6.2 + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + + + + \ No newline at end of file diff --git a/spring-cloud-data-flow/apache-spark-job/src/main/java/com/baeldung/spring/cloud/PiApproximation.java b/spring-cloud-data-flow/apache-spark-job/src/main/java/com/baeldung/spring/cloud/PiApproximation.java new file mode 100644 index 0000000000..dfead21728 --- /dev/null +++ b/spring-cloud-data-flow/apache-spark-job/src/main/java/com/baeldung/spring/cloud/PiApproximation.java @@ -0,0 +1,39 @@ +package com.baeldung.spring.cloud; + +import org.apache.spark.SparkConf; +import org.apache.spark.api.java.JavaRDD; +import org.apache.spark.api.java.JavaSparkContext; +import org.apache.spark.api.java.function.Function; +import org.apache.spark.api.java.function.Function2; +import org.apache.spark.rdd.RDD; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class PiApproximation { + public static void main(String[] args) { + SparkConf conf = new SparkConf().setAppName("BaeldungPIApproximation"); + JavaSparkContext context = new JavaSparkContext(conf); + int slices = args.length >= 1 ? Integer.valueOf(args[0]) : 2; + int n = (100000L * slices) > Integer.MAX_VALUE ? Integer.MAX_VALUE : 100000 * slices; + + List xs = IntStream.rangeClosed(0, n) + .mapToObj(element -> Integer.valueOf(element)) + .collect(Collectors.toList()); + + JavaRDD dataSet = context.parallelize(xs, slices); + + JavaRDD pointsInsideTheCircle = dataSet.map(integer -> { + double x = Math.random() * 2 - 1; + double y = Math.random() * 2 - 1; + return (x*x + y*y ) < 1 ? 1: 0; + }); + + int count = pointsInsideTheCircle.reduce((integer, integer2) -> integer + integer2); + + System.out.println("The pi was estimated as:" + count / n); + + context.stop(); + } +} diff --git a/spring-cloud-data-flow/pom.xml b/spring-cloud-data-flow/pom.xml index daf8ebd2c8..36a780c28d 100644 --- a/spring-cloud-data-flow/pom.xml +++ b/spring-cloud-data-flow/pom.xml @@ -20,6 +20,7 @@ log-sink batch-job etl + apache-spark-job diff --git a/spring-cloud/spring-cloud-gateway/README.MD b/spring-cloud/spring-cloud-gateway/README.MD index 48fbf41b8e..d945ae949c 100644 --- a/spring-cloud/spring-cloud-gateway/README.MD +++ b/spring-cloud/spring-cloud-gateway/README.MD @@ -1,2 +1,2 @@ ### Relevant Articles: -- [Explore the new Spring Cloud Gateway](http://www.baeldung.com/spring-cloud-gateway) +- [Exploring the new Spring Cloud Gateway](http://www.baeldung.com/spring-cloud-gateway) diff --git a/spring-jms/README.md b/spring-jms/README.md index b942cc72a0..55e74f18ff 100644 --- a/spring-jms/README.md +++ b/spring-jms/README.md @@ -1,2 +1,2 @@ ### Relevant Articles: -- [An Introduction To Spring JMS](http://www.baeldung.com/spring-jms) +- [Getting Started with Spring JMS](http://www.baeldung.com/spring-jms) diff --git a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsErrorHandler.java b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsErrorHandler.java new file mode 100644 index 0000000000..220b2744f3 --- /dev/null +++ b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsErrorHandler.java @@ -0,0 +1,17 @@ +package com.baeldung.spring.jms; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ErrorHandler; + +public class SampleJmsErrorHandler implements ErrorHandler { + + private static final Logger LOG = LoggerFactory.getLogger(SampleJmsErrorHandler.class); + + @Override + public void handleError(Throwable t) { + LOG.warn("In default jms error handler..."); + LOG.error("Error Message : {}", t.getMessage()); + } + +} diff --git a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsMessageSender.java b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsMessageSender.java index 927762f05b..d3f09618fb 100644 --- a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsMessageSender.java +++ b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsMessageSender.java @@ -26,4 +26,8 @@ public class SampleJmsMessageSender { public void sendMessage(final Employee employee) { this.jmsTemplate.convertAndSend(employee); } + + public void sendTextMessage(String msg) { + this.jmsTemplate.send(queue, s -> s.createTextMessage(msg)); + } } diff --git a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleListener.java b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleListener.java index f35c22e144..87627c47e7 100644 --- a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleListener.java +++ b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleListener.java @@ -27,6 +27,9 @@ public class SampleListener implements MessageListener { try { String msg = ((TextMessage) message).getText(); System.out.println("Received message: " + msg); + if (msg == null) { + throw new IllegalArgumentException("Null value received..."); + } } catch (JMSException ex) { throw new RuntimeException(ex); } @@ -37,4 +40,5 @@ public class SampleListener implements MessageListener { Map map = (Map) this.jmsTemplate.receiveAndConvert(); return new Employee((String) map.get("name"), (Integer) map.get("age")); } + } diff --git a/spring-jms/src/main/resources/applicationContext.xml b/spring-jms/src/main/resources/applicationContext.xml index 28bf848e59..97a90e0bf2 100644 --- a/spring-jms/src/main/resources/applicationContext.xml +++ b/spring-jms/src/main/resources/applicationContext.xml @@ -1,51 +1,48 @@ - - - - - - - - - - + + + + + + - - - + + + - + + + + + + + - - - + + + + + - - - - + + + + + - + - - - - - - - - - - - - - + + + + + + + diff --git a/spring-jms/src/test/java/com/baeldung/spring/jms/DefaultTextMessageSenderIntegrationTest.java b/spring-jms/src/test/java/com/baeldung/spring/jms/DefaultTextMessageSenderIntegrationTest.java index f87d26b144..f23ead4d69 100644 --- a/spring-jms/src/test/java/com/baeldung/spring/jms/DefaultTextMessageSenderIntegrationTest.java +++ b/spring-jms/src/test/java/com/baeldung/spring/jms/DefaultTextMessageSenderIntegrationTest.java @@ -8,12 +8,14 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class DefaultTextMessageSenderIntegrationTest { private static SampleJmsMessageSender messageProducer; + private static SampleListener messageListener; @SuppressWarnings("resource") @BeforeClass public static void setUp() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:EmbeddedActiveMQ.xml", "classpath:applicationContext.xml"); messageProducer = (SampleJmsMessageSender) applicationContext.getBean("SampleJmsMessageSender"); + messageListener = (SampleListener) applicationContext.getBean("messageListener"); } @Test @@ -21,4 +23,9 @@ public class DefaultTextMessageSenderIntegrationTest { messageProducer.simpleSend(); } + @Test + public void testSendTextMessage() { + messageProducer.sendTextMessage(null); + } + } diff --git a/spring-katharsis/README.md b/spring-katharsis/README.md index cf2a001760..2082de2dda 100644 --- a/spring-katharsis/README.md +++ b/spring-katharsis/README.md @@ -6,4 +6,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [JSON API in a Java Web Application](http://www.baeldung.com/json-api-java-spring-web-app) +- [JSON API in a Spring Application](http://www.baeldung.com/json-api-java-spring-web-app) diff --git a/spring-mvc-simple/README.md b/spring-mvc-simple/README.md index 755e0932fc..cd4ad5aba2 100644 --- a/spring-mvc-simple/README.md +++ b/spring-mvc-simple/README.md @@ -8,3 +8,4 @@ - [Guide to Spring Email](http://www.baeldung.com/spring-email) - [Request Method Not Supported (405) in Spring](https://www.baeldung.com/spring-request-method-not-supported-405) - [Spring @RequestParam Annotation](https://www.baeldung.com/spring-request-param) +- [Validating RequestParams and PathVariables in Spring](https://www.baeldung.com/spring-validate-requestparam-pathvariable) diff --git a/spring-mvc-simple/pom.xml b/spring-mvc-simple/pom.xml index 8c2661cc27..b9ed3a3e81 100644 --- a/spring-mvc-simple/pom.xml +++ b/spring-mvc-simple/pom.xml @@ -17,7 +17,7 @@ org.springframework spring-oxm - ${spring-oxm.version} + ${spring.version} com.sun.mail @@ -181,7 +181,6 @@ 1.4.9 5.1.0 20180130 - 5.0.2.RELEASE 3.0.8 diff --git a/spring-mvc-xml/README.md b/spring-mvc-xml/README.md index 3199118281..dbc6125424 100644 --- a/spring-mvc-xml/README.md +++ b/spring-mvc-xml/README.md @@ -8,7 +8,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [Servlet Session Timeout](http://www.baeldung.com/servlet-session-timeout) +- [Java Session Timeout](http://www.baeldung.com/servlet-session-timeout) - [Returning Image/Media Data with Spring MVC](http://www.baeldung.com/spring-mvc-image-media-data) - [Geolocation by IP in Java](http://www.baeldung.com/geolocation-by-ip-with-maxmind) - [Guide to JavaServer Pages (JSP)](http://www.baeldung.com/jsp) diff --git a/spring-remoting/README.md b/spring-remoting/README.md index 7d344a3f27..0898b9b002 100644 --- a/spring-remoting/README.md +++ b/spring-remoting/README.md @@ -4,7 +4,7 @@ - [Intro to Spring Remoting with HTTP Invokers](http://www.baeldung.com/spring-remoting-http-invoker) - [Spring Remoting with Hessian and Burlap](http://www.baeldung.com/spring-remoting-hessian-burlap) - [Spring Remoting with AMQP](http://www.baeldung.com/spring-remoting-amqp) -- [Spring Remoting with JMS](http://www.baeldung.com/spring-remoting-jms) +- [Spring Remoting with JMS and ActiveMQ](http://www.baeldung.com/spring-remoting-jms) - [Spring Remoting with RMI](http://www.baeldung.com/spring-remoting-rmi) ### Overview diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md index 32b65ccc6a..ed6df1675f 100644 --- a/spring-rest-full/README.md +++ b/spring-rest-full/README.md @@ -12,7 +12,7 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) - [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) +- [Bootstrap a Web Application with Spring 5](http://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) - [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic) diff --git a/spring-rest/src/main/java/com/baeldung/produceimage/README.md b/spring-rest/src/main/java/com/baeldung/produceimage/README.md index acd546598d..4aeadea546 100644 --- a/spring-rest/src/main/java/com/baeldung/produceimage/README.md +++ b/spring-rest/src/main/java/com/baeldung/produceimage/README.md @@ -1,3 +1,3 @@ ### Relevant articles -- [Returning an Image or a File with Spring](http://www.baeldung.com/spring-controller-return-image-file) +- [Download an Image or a File with Spring MVC](http://www.baeldung.com/spring-controller-return-image-file) diff --git a/spring-resttemplate/README.md b/spring-resttemplate/README.md index 1c8ddf73f9..353e9f955e 100644 --- a/spring-resttemplate/README.md +++ b/spring-resttemplate/README.md @@ -4,7 +4,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [Spring RestTemplate Tutorial](http://www.baeldung.com/rest-template) +- [The Guide to RestTemplate](http://www.baeldung.com/rest-template) - [Exploring the Spring Boot TestRestTemplate](http://www.baeldung.com/spring-boot-testresttemplate) - [Spring RestTemplate Error Handling](http://www.baeldung.com/spring-rest-template-error-handling) - [Configure a RestTemplate with RestTemplateBuilder](http://www.baeldung.com/spring-rest-template-builder) diff --git a/spring-security-client/pom.xml b/spring-security-client/pom.xml new file mode 100644 index 0000000000..96ac837a09 --- /dev/null +++ b/spring-security-client/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + spring-security-client + spring-security-client + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + spring-security-jsp-authentication + spring-security-jsp-authorize + spring-security-jsp-config + spring-security-mvc + spring-security-thymeleaf-authentication + spring-security-thymeleaf-authorize + spring-security-thymeleaf-config + + diff --git a/spring-security-core/README.md b/spring-security-core/README.md index f7b3f6dffe..b38dc061b4 100644 --- a/spring-security-core/README.md +++ b/spring-security-core/README.md @@ -7,6 +7,6 @@ mvn clean install ``` ### Relevant Articles: -- [Intro to @PreFilter and @PostFilter in Spring Security](http://www.baeldung.com/spring-security-prefilter-postfilter) +- [Spring Security – @PreFilter and @PostFilter](http://www.baeldung.com/spring-security-prefilter-postfilter) - [Spring Boot Authentication Auditing Support](http://www.baeldung.com/spring-boot-authentication-audit) - [Introduction to Spring Method Security](http://www.baeldung.com/spring-security-method-security) diff --git a/spring-security-mvc-custom/pom.xml b/spring-security-mvc-custom/pom.xml index b4239fb2b8..7c60a8e18a 100644 --- a/spring-security-mvc-custom/pom.xml +++ b/spring-security-mvc-custom/pom.xml @@ -21,17 +21,17 @@ org.springframework.security spring-security-web - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-config - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-taglibs - ${org.springframework.security.version} + ${spring-security.version} @@ -144,7 +144,7 @@ org.springframework.security spring-security-test - ${org.springframework.security.version} + ${spring-security.version} test @@ -192,9 +192,6 @@
- - 5.0.6.RELEASE - 3.1.0 1.2 diff --git a/spring-security-mvc-jsonview/README.md b/spring-security-mvc-jsonview/README.md new file mode 100644 index 0000000000..35c806e856 --- /dev/null +++ b/spring-security-mvc-jsonview/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Filtering Jackson JSON Output Based on Spring Security Role](https://www.baeldung.com/spring-security-role-filter-json) diff --git a/spring-security-mvc-jsonview/pom.xml b/spring-security-mvc-jsonview/pom.xml index 7f1129128f..b6d3e7e399 100644 --- a/spring-security-mvc-jsonview/pom.xml +++ b/spring-security-mvc-jsonview/pom.xml @@ -38,17 +38,17 @@ org.springframework.security spring-security-web - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-config - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-taglibs - ${org.springframework.security.version} + ${spring-security.version} @@ -133,7 +133,7 @@ org.springframework.security spring-security-test - ${org.springframework.security.version} + ${spring-security.version} test @@ -206,9 +206,6 @@ - - 5.0.5.RELEASE - 3.1.0 1.2 diff --git a/spring-security-mvc-login/pom.xml b/spring-security-mvc-login/pom.xml index bbdff6fc2f..048297bbd4 100644 --- a/spring-security-mvc-login/pom.xml +++ b/spring-security-mvc-login/pom.xml @@ -21,17 +21,17 @@ org.springframework.security spring-security-web - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-config - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-taglibs - ${org.springframework.security.version} + ${spring-security.version} @@ -116,7 +116,7 @@ org.springframework.security spring-security-test - ${org.springframework.security.version} + ${spring-security.version} test @@ -175,7 +175,6 @@ - 5.0.5.RELEASE 3.1.0 diff --git a/spring-security-mvc-session/README.md b/spring-security-mvc-session/README.md index fc44209640..ce40ed5f5f 100644 --- a/spring-security-mvc-session/README.md +++ b/spring-security-mvc-session/README.md @@ -7,7 +7,7 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [HttpSessionListener Example – Monitoring](http://www.baeldung.com/httpsessionlistener_with_metrics) -- [Spring Security Session Management](http://www.baeldung.com/spring-security-session) +- [Control the Session with Spring Security](http://www.baeldung.com/spring-security-session) ### Build the Project diff --git a/spring-security-rest-basic-auth/README.md b/spring-security-rest-basic-auth/README.md index f92fcfe36b..30da3afbcf 100644 --- a/spring-security-rest-basic-auth/README.md +++ b/spring-security-rest-basic-auth/README.md @@ -6,8 +6,8 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: -- [RestTemplate with Basic Authentication in Spring](http://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring) +- [Basic Authentication with the RestTemplate](http://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring) - [HttpClient Timeout](http://www.baeldung.com/httpclient-timeout) - [HttpClient with SSL](http://www.baeldung.com/httpclient-ssl) -- [Writing a Custom Filter in Spring Security](http://www.baeldung.com/spring-security-custom-filter) +- [A Custom Filter in the Spring Security Filter Chain](http://www.baeldung.com/spring-security-custom-filter) - [Spring Security Basic Authentication](http://www.baeldung.com/spring-security-basic-authentication) diff --git a/spring-security-rest/pom.xml b/spring-security-rest/pom.xml index 37c743e896..24f1c5807a 100644 --- a/spring-security-rest/pom.xml +++ b/spring-security-rest/pom.xml @@ -21,12 +21,12 @@ org.springframework.security spring-security-web - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-config - ${org.springframework.security.version} + ${spring-security.version} @@ -144,7 +144,7 @@ org.springframework.security spring-security-test - ${org.springframework.security.version} + ${spring-security.version} test @@ -274,7 +274,6 @@ - 5.1.0.RELEASE 0.25.0.RELEASE diff --git a/spring-soap/README.md b/spring-soap/README.md new file mode 100644 index 0000000000..8d96350e1e --- /dev/null +++ b/spring-soap/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Creating a SOAP Web Service with Spring](https://www.baeldung.com/spring-boot-soap-web-service) diff --git a/spring-static-resources/pom.xml b/spring-static-resources/pom.xml index aedf88e384..fc2b3336bc 100644 --- a/spring-static-resources/pom.xml +++ b/spring-static-resources/pom.xml @@ -20,17 +20,17 @@ org.springframework.security spring-security-web - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-config - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-taglibs - ${org.springframework.security.version} + ${spring-security.version} @@ -196,9 +196,6 @@ - - 5.0.6.RELEASE - 1.8.9 2.3.2-b02 diff --git a/testing-modules/junit-5/README.md b/testing-modules/junit-5/README.md index d46f8bf1cf..d686396a1d 100644 --- a/testing-modules/junit-5/README.md +++ b/testing-modules/junit-5/README.md @@ -3,12 +3,12 @@ - [A Guide to JUnit 5](http://www.baeldung.com/junit-5) - [A Guide to @RepeatedTest in Junit 5](http://www.baeldung.com/junit-5-repeated-test) - [Guide to Dynamic Tests in Junit 5](http://www.baeldung.com/junit5-dynamic-tests) -- [A Guied to JUnit 5 Extensions](http://www.baeldung.com/junit-5-extensions) +- [A Guide to JUnit 5 Extensions](http://www.baeldung.com/junit-5-extensions) - [Inject Parameters into JUnit Jupiter Unit Tests](http://www.baeldung.com/junit-5-parameters) - [Mockito and JUnit 5 – Using ExtendWith](http://www.baeldung.com/mockito-junit-5-extension) - [JUnit 5 – @RunWith](http://www.baeldung.com/junit-5-runwith) - [JUnit 5 @Test Annotation](http://www.baeldung.com/junit-5-test-annotation) -- [JUnit Assert an Exception is Thrown](http://www.baeldung.com/junit-assert-exception) +- [Assert an Exception is Thrown in JUnit 4 and 5](http://www.baeldung.com/junit-assert-exception) - [@Before vs @BeforeClass vs @BeforeEach vs @BeforeAll](http://www.baeldung.com/junit-before-beforeclass-beforeeach-beforeall) - [Migrating from JUnit 4 to JUnit 5](http://www.baeldung.com/junit-5-migration) - [JUnit5 Programmatic Extension Registration with @RegisterExtension](http://www.baeldung.com/junit-5-registerextension-annotation) diff --git a/testing-modules/mockito/README.md b/testing-modules/mockito/README.md index 158a1918e7..59954784f9 100644 --- a/testing-modules/mockito/README.md +++ b/testing-modules/mockito/README.md @@ -7,7 +7,7 @@ - [Mockito Verify Cookbook](http://www.baeldung.com/mockito-verify) - [Mockito When/Then Cookbook](http://www.baeldung.com/mockito-behavior) - [Mockito – Using Spies](http://www.baeldung.com/mockito-spy) -- [Mockito – @Mock, @Spy, @Captor and @InjectMocks](http://www.baeldung.com/mockito-annotations) +- [Getting Started with Mockito @Mock, @Spy, @Captor and @InjectMocks](http://www.baeldung.com/mockito-annotations) - [Mockito’s Mock Methods](http://www.baeldung.com/mockito-mock-methods) - [Introduction to PowerMock](http://www.baeldung.com/intro-to-powermock) - [Mocking Exception Throwing using Mockito](http://www.baeldung.com/mockito-exceptions) diff --git a/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java b/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java new file mode 100644 index 0000000000..306f53297a --- /dev/null +++ b/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java @@ -0,0 +1,38 @@ +package org.baeldung.mockito.misusing; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.After; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.exceptions.misusing.NotAMockException; +import org.mockito.internal.progress.ThreadSafeMockingProgress; + +public class MockitoMisusingUnitTest { + + @After + public void tearDown() { + ThreadSafeMockingProgress.mockingProgress().reset(); + } + + @Test + public void givenNotASpy_whenDoReturn_thenThrowNotAMock() { + try { + List list = new ArrayList(); + + Mockito.doReturn(100, Mockito.withSettings().lenient()) + .when(list) + .size(); + + fail("Should have thrown a NotAMockException because 'list' is not a mock!"); + } catch (NotAMockException e) { + assertThat(e.getMessage(), containsString("Argument passed to when() is not a mock!")); + } + } + +} diff --git a/testing-modules/pom.xml b/testing-modules/pom.xml new file mode 100644 index 0000000000..39047fb756 --- /dev/null +++ b/testing-modules/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + testing-modules + testing-modules + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + gatling + groovy-spock + junit-5 + junit5-migration + load-testing-comparison + mockito + mockito-2 + mocks + mockserver + parallel-tests-junit + rest-assured + rest-testing + + selenium-junit-testng + spring-testing + test-containers + testing + testng + + diff --git a/testing-modules/testing/README.md b/testing-modules/testing/README.md index 849b578a55..e96b26ab41 100644 --- a/testing-modules/testing/README.md +++ b/testing-modules/testing/README.md @@ -3,7 +3,7 @@ ## Mutation Testing ### Relevant Articles: -- [Introduction to Mutation Testing Using the PITest Library](http://www.baeldung.com/java-mutation-testing-with-pitest) +- [Mutation Testing with PITest](http://www.baeldung.com/java-mutation-testing-with-pitest) - [Intro to JaCoCo](http://www.baeldung.com/jacoco) - [AssertJ’s Java 8 Features](http://www.baeldung.com/assertJ-java-8-features) - [AssertJ for Guava](http://www.baeldung.com/assertJ-for-guava) diff --git a/vavr/README.md b/vavr/README.md index 0857765ec6..266cae91bb 100644 --- a/vavr/README.md +++ b/vavr/README.md @@ -4,7 +4,7 @@ - [Guide to Pattern Matching in Vavr](http://www.baeldung.com/vavr-pattern-matching) - [Property Testing Example With Vavr](http://www.baeldung.com/vavr-property-testing) - [Exceptions in Lambda Expression Using Vavr](http://www.baeldung.com/exceptions-using-vavr) -- [Vavr (ex-Javaslang) Support in Spring Data](http://www.baeldung.com/spring-vavr) +- [Vavr Support in Spring Data](http://www.baeldung.com/spring-vavr) - [Introduction to Vavr’s Validation API](http://www.baeldung.com/vavr-validation-api) - [Guide to Collections API in Vavr](http://www.baeldung.com/vavr-collections) - [Collection Factory Methods for Vavr](http://www.baeldung.com/vavr-collection-factory-methods)