Date: Sat, 28 Mar 2020 16:48:04 +0530
Subject: [PATCH 030/276] JAVA-623: Moved 3 articles from core-java-security to
security-2
---
.../core-java-security/README.md | 5 +-
core-java-modules/core-java-security/pom.xml | 15 --
.../baeldung/hashing/DigestAlgorithms.java | 9 --
.../baeldung/hashing/Keccak256Hashing.java | 30 ----
.../com/baeldung/hashing/SHA256Hashing.java | 39 -----
.../com/baeldung/hashing/SHA3Hashing.java | 45 ------
.../com/baeldung/hashing/SHACommonUtils.java | 16 --
.../passwordhashing/PBKDF2Hasher.java | 149 ------------------
.../passwordhashing/SHA512Hasher.java | 35 ----
.../passwordhashing/SimplePBKDF2Hasher.java | 18 ---
.../hashing/Keccak256HashingUnitTest.java | 22 ---
.../hashing/SHA256HashingUnitTest.java | 35 ----
.../baeldung/hashing/SHA3HashingUnitTest.java | 38 -----
.../baeldung/java/md5/JavaMD5UnitTest.java | 75 ---------
.../passwordhashing/PBKDF2HasherUnitTest.java | 41 -----
.../passwordhashing/SHA512HasherUnitTest.java | 70 --------
.../src/test/resources/test_md5.txt | 1 -
17 files changed, 2 insertions(+), 641 deletions(-)
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java
delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java
delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java
delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
delete mode 100644 core-java-modules/core-java-security/src/test/resources/test_md5.txt
diff --git a/core-java-modules/core-java-security/README.md b/core-java-modules/core-java-security/README.md
index ff9b1eef14..83b12793b5 100644
--- a/core-java-modules/core-java-security/README.md
+++ b/core-java-modules/core-java-security/README.md
@@ -3,17 +3,16 @@
This module contains articles about core Java Security
### Relevant Articles:
-- [MD5 Hashing in Java](http://www.baeldung.com/java-md5)
+
- [Guide to the Cipher Class](http://www.baeldung.com/java-cipher-class)
- [Introduction to SSL in Java](http://www.baeldung.com/java-ssl)
- [Java KeyStore API](http://www.baeldung.com/java-keystore)
- [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 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)
- [The Java SecureRandom Class](https://www.baeldung.com/java-secure-random)
- [An Introduction to Java SASL](https://www.baeldung.com/java-sasl)
- [A Guide to Java GSS API](https://www.baeldung.com/java-gss)
- [Intro to the Java SecurityManager](https://www.baeldung.com/java-security-manager)
+- More articles: [[next -->]](/core-java-modules/core-java-security-2)
diff --git a/core-java-modules/core-java-security/pom.xml b/core-java-modules/core-java-security/pom.xml
index a46c2e2d40..96024a73a1 100644
--- a/core-java-modules/core-java-security/pom.xml
+++ b/core-java-modules/core-java-security/pom.xml
@@ -24,24 +24,9 @@
${assertj-core.version}
test
-
-
- commons-codec
- commons-codec
- ${commons-codec.version}
-
-
- org.bouncycastle
- bcprov-jdk15on
- ${bouncycastle.version}
-
-
- 1.60
- 1.11
-
3.10.0
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java
deleted file mode 100644
index 94dd22ff4b..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.baeldung.hashing;
-
-public class DigestAlgorithms {
-
- public static final String SHA3_256 = "SHA3-256";
- public static final String SHA_256 = "SHA-256";
- public static final String KECCAK_256 = "Keccak-256";
-
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java
deleted file mode 100644
index 19fc4cf059..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.baeldung.hashing;
-
-import org.bouncycastle.jcajce.provider.digest.Keccak;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Hex;
-
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.Security;
-
-import static com.baeldung.hashing.DigestAlgorithms.KECCAK_256;
-import static com.baeldung.hashing.SHACommonUtils.bytesToHex;
-
-public class Keccak256Hashing {
-
- public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException {
- Security.addProvider(new BouncyCastleProvider());
- final MessageDigest digest = MessageDigest.getInstance(KECCAK_256);
- final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
- return bytesToHex(encodedhash);
- }
-
- public static String hashWithBouncyCastle(final String originalString) {
- Keccak.Digest256 digest256 = new Keccak.Digest256();
- byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8));
- return new String(Hex.encode(hashbytes));
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java
deleted file mode 100644
index ec008cebab..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.baeldung.hashing;
-
-import com.google.common.hash.Hashing;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.bouncycastle.util.encoders.Hex;
-
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import static com.baeldung.hashing.DigestAlgorithms.SHA_256;
-import static com.baeldung.hashing.SHACommonUtils.bytesToHex;
-
-public class SHA256Hashing {
-
- public static String HashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException {
- final MessageDigest digest = MessageDigest.getInstance(SHA_256);
- final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
- return bytesToHex(encodedhash);
- }
-
- public static String hashWithGuava(final String originalString) {
- final String sha256hex = Hashing.sha256().hashString(originalString, StandardCharsets.UTF_8).toString();
- return sha256hex;
- }
-
- public static String HashWithApacheCommons(final String originalString) {
- final String sha256hex = DigestUtils.sha256Hex(originalString);
- return sha256hex;
- }
-
- public static String HashWithBouncyCastle(final String originalString) throws NoSuchAlgorithmException {
- final MessageDigest digest = MessageDigest.getInstance(SHA_256);
- final byte[] hash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
- final String sha256hex = new String(Hex.encode(hash));
- return sha256hex;
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java
deleted file mode 100644
index eb363205b1..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.baeldung.hashing;
-
-import com.google.common.hash.Hashing;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.bouncycastle.crypto.digests.SHA3Digest;
-import org.bouncycastle.jcajce.provider.digest.SHA3;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Hex;
-
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.Security;
-
-import static com.baeldung.hashing.DigestAlgorithms.SHA3_256;
-import static com.baeldung.hashing.SHACommonUtils.bytesToHex;
-
-public class SHA3Hashing {
-
- /* works with JDK9+ only */
- public static String hashWithJavaMessageDigestJDK9(final String originalString) throws NoSuchAlgorithmException {
- final MessageDigest digest = MessageDigest.getInstance(SHA3_256);
- final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
- return bytesToHex(hashbytes);
- }
-
- public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException {
- Security.addProvider(new BouncyCastleProvider());
- final MessageDigest digest = MessageDigest.getInstance(SHA3_256);
- final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
- return bytesToHex(hashbytes);
- }
-
- /* works with JDK9+ only */
- public static String hashWithApacheCommonsJDK9(final String originalString) {
- return new DigestUtils(SHA3_256).digestAsHex(originalString);
- }
-
- public static String hashWithBouncyCastle(final String originalString) {
- SHA3.Digest256 digest256 = new SHA3.Digest256();
- byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8));
- return new String(Hex.encode(hashbytes));
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java
deleted file mode 100644
index 0f28408083..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.baeldung.hashing;
-
-class SHACommonUtils {
-
- public static String bytesToHex(byte[] hash) {
- StringBuffer hexString = new StringBuffer();
- for (byte h : hash) {
- String hex = Integer.toHexString(0xff & h);
- if (hex.length() == 1)
- hexString.append('0');
- hexString.append(hex);
- }
- return hexString.toString();
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
deleted file mode 100644
index e2259e4249..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package com.baeldung.passwordhashing;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.KeySpec;
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.PBEKeySpec;
-
-/**
- * Hash passwords for storage, and test passwords against password tokens.
- *
- * Instances of this class can be used concurrently by multiple threads.
- *
- * @author erickson
- * @see StackOverflow
- */
-public final class PBKDF2Hasher
-{
-
- /**
- * Each token produced by this class uses this identifier as a prefix.
- */
- public static final String ID = "$31$";
-
- /**
- * The minimum recommended cost, used by default
- */
- public static final int DEFAULT_COST = 16;
-
- private static final String ALGORITHM = "PBKDF2WithHmacSHA1";
-
- private static final int SIZE = 128;
-
- private static final Pattern layout = Pattern.compile("\\$31\\$(\\d\\d?)\\$(.{43})");
-
- private final SecureRandom random;
-
- private final int cost;
-
- public PBKDF2Hasher()
- {
- this(DEFAULT_COST);
- }
-
- /**
- * Create a password manager with a specified cost
- *
- * @param cost the exponential computational cost of hashing a password, 0 to 30
- */
- public PBKDF2Hasher(int cost)
- {
- iterations(cost); /* Validate cost */
- this.cost = cost;
- this.random = new SecureRandom();
- }
-
- private static int iterations(int cost)
- {
- if ((cost < 0) || (cost > 30))
- throw new IllegalArgumentException("cost: " + cost);
- return 1 << cost;
- }
-
- /**
- * Hash a password for storage.
- *
- * @return a secure authentication token to be stored for later authentication
- */
- public String hash(char[] password)
- {
- byte[] salt = new byte[SIZE / 8];
- random.nextBytes(salt);
- byte[] dk = pbkdf2(password, salt, 1 << cost);
- byte[] hash = new byte[salt.length + dk.length];
- System.arraycopy(salt, 0, hash, 0, salt.length);
- System.arraycopy(dk, 0, hash, salt.length, dk.length);
- Base64.Encoder enc = Base64.getUrlEncoder().withoutPadding();
- return ID + cost + '$' + enc.encodeToString(hash);
- }
-
- /**
- * Authenticate with a password and a stored password token.
- *
- * @return true if the password and token match
- */
- public boolean checkPassword(char[] password, String token)
- {
- Matcher m = layout.matcher(token);
- if (!m.matches())
- throw new IllegalArgumentException("Invalid token format");
- int iterations = iterations(Integer.parseInt(m.group(1)));
- byte[] hash = Base64.getUrlDecoder().decode(m.group(2));
- byte[] salt = Arrays.copyOfRange(hash, 0, SIZE / 8);
- byte[] check = pbkdf2(password, salt, iterations);
- int zero = 0;
- for (int idx = 0; idx < check.length; ++idx)
- zero |= hash[salt.length + idx] ^ check[idx];
- return zero == 0;
- }
-
- private static byte[] pbkdf2(char[] password, byte[] salt, int iterations)
- {
- KeySpec spec = new PBEKeySpec(password, salt, iterations, SIZE);
- try {
- SecretKeyFactory f = SecretKeyFactory.getInstance(ALGORITHM);
- return f.generateSecret(spec).getEncoded();
- }
- catch (NoSuchAlgorithmException ex) {
- throw new IllegalStateException("Missing algorithm: " + ALGORITHM, ex);
- }
- catch (InvalidKeySpecException ex) {
- throw new IllegalStateException("Invalid SecretKeyFactory", ex);
- }
- }
-
- /**
- * Hash a password in an immutable {@code String}.
- *
- * Passwords should be stored in a {@code char[]} so that it can be filled
- * with zeros after use instead of lingering on the heap and elsewhere.
- *
- * @deprecated Use {@link #hash(char[])} instead
- */
- @Deprecated
- public String hash(String password)
- {
- return hash(password.toCharArray());
- }
-
- /**
- * Authenticate with a password in an immutable {@code String} and a stored
- * password token.
- *
- * @deprecated Use {@link #checkPassword(char[],String)} instead.
- * @see #hash(String)
- */
- @Deprecated
- public boolean checkPassword(String password, String token)
- {
- return checkPassword(password.toCharArray(), token);
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
deleted file mode 100644
index 4f5337f963..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.baeldung.passwordhashing;
-
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-
-/** A really simple SHA_512 Encryption example.
- *
- */
-public class SHA512Hasher {
-
- public String hash(String passwordToHash, byte[] salt){
- String generatedPassword = null;
- try {
- MessageDigest md = MessageDigest.getInstance("SHA-512");
- md.update(salt);
- byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
- StringBuilder sb = new StringBuilder();
- for(int i=0; i< bytes.length ;i++){
- sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
- }
- generatedPassword = sb.toString();
- }
- catch (NoSuchAlgorithmException e){
- e.printStackTrace();
- }
- return generatedPassword;
- }
-
- public boolean checkPassword(String hash, String attempt, byte[] salt){
- String generatedHash = hash(attempt, salt);
- return hash.equals(generatedHash);
- }
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
deleted file mode 100644
index 36c9b65070..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.baeldung.passwordhashing;
-
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.PBEKeySpec;
-import java.security.spec.KeySpec;
-
-/** A really simple SimplePBKDF2 Encryption example.
- *
- */
-public class SimplePBKDF2Hasher {
-
- public static String hashSimple(String password, byte[] salt) throws Exception{
- KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
- SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
- byte[] hash = f.generateSecret(spec).getEncoded();
- return String.valueOf(hash);
- }
-}
diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java
deleted file mode 100644
index 9ed35c8834..0000000000
--- a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.baeldung.hashing;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class Keccak256HashingUnitTest {
-
- private static String originalValue = "abc123";
- private static String hashedValue = "719accc61a9cc126830e5906f9d672d06eab6f8597287095a2c55a8b775e7016";
-
- @Test public void testHashWithJavaMessageDigest() throws Exception {
- final String currentHashedValue = Keccak256Hashing.hashWithJavaMessageDigest(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- @Test public void testHashWithBouncyCastle() {
- final String currentHashedValue = Keccak256Hashing.hashWithBouncyCastle(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
deleted file mode 100644
index 6bc9ad2cc6..0000000000
--- a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.baeldung.hashing;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class SHA256HashingUnitTest {
-
- private static String originalValue = "abc123";
- private static String hashedValue = "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090";
-
- @Test
- public void testHashWithJavaMessageDigest() throws Exception {
- final String currentHashedValue = SHA256Hashing.HashWithJavaMessageDigest(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- @Test
- public void testHashWithGuava() throws Exception {
- final String currentHashedValue = SHA256Hashing.hashWithGuava(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- @Test
- public void testHashWithApacheCommans() throws Exception {
- final String currentHashedValue = SHA256Hashing.HashWithApacheCommons(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- @Test
- public void testHashWithBouncyCastle() throws Exception {
- final String currentHashedValue = SHA256Hashing.HashWithBouncyCastle(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java
deleted file mode 100644
index fffab96405..0000000000
--- a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.baeldung.hashing;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class SHA3HashingUnitTest {
-
- private static String originalValue = "abc123";
- private static String hashedValue = "f58fa3df820114f56e1544354379820cff464c9c41cb3ca0ad0b0843c9bb67ee";
-
- /* works with JDK9+ only */
- //@Test
- public void testHashWithJavaMessageDigestJDK9() throws Exception {
- final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigestJDK9(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- @Test
- public void testHashWithJavaMessageDigest() throws Exception {
- final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigest(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- /* works with JDK9+ only */
- //@Test
- public void testHashWithApacheCommonsJDK9() {
- final String currentHashedValue = SHA3Hashing.hashWithApacheCommonsJDK9(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- @Test
- public void testHashWithBouncyCastle() {
- final String currentHashedValue = SHA3Hashing.hashWithBouncyCastle(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java
deleted file mode 100644
index 67d6918c09..0000000000
--- a/core-java-modules/core-java-security/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.baeldung.java.md5;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import javax.xml.bind.DatatypeConverter;
-
-import org.apache.commons.codec.digest.DigestUtils;
-import org.junit.Test;
-
-import com.google.common.hash.HashCode;
-import com.google.common.hash.Hashing;
-
-public class JavaMD5UnitTest {
-
- String filename = "src/test/resources/test_md5.txt";
- String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
-
- String hash = "35454B055CC325EA1AF2126E27707052";
- String password = "ILoveJava";
-
- @Test
- public void givenPassword_whenHashing_thenVerifying() throws NoSuchAlgorithmException {
- String hash = "35454B055CC325EA1AF2126E27707052";
- String password = "ILoveJava";
-
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.update(password.getBytes());
- byte[] digest = md.digest();
- String myHash = DatatypeConverter.printHexBinary(digest).toUpperCase();
-
- assertThat(myHash.equals(hash)).isTrue();
- }
-
- @Test
- public void givenFile_generatingChecksum_thenVerifying() throws NoSuchAlgorithmException, IOException {
- String filename = "src/test/resources/test_md5.txt";
- String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
-
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.update(Files.readAllBytes(Paths.get(filename)));
- byte[] digest = md.digest();
- String myChecksum = DatatypeConverter.printHexBinary(digest).toUpperCase();
-
- assertThat(myChecksum.equals(checksum)).isTrue();
- }
-
- @Test
- public void givenPassword_whenHashingUsingCommons_thenVerifying() {
- String hash = "35454B055CC325EA1AF2126E27707052";
- String password = "ILoveJava";
-
- String md5Hex = DigestUtils.md5Hex(password).toUpperCase();
-
- assertThat(md5Hex.equals(hash)).isTrue();
- }
-
- @Test
- public void givenFile_whenChecksumUsingGuava_thenVerifying() throws IOException {
- String filename = "src/test/resources/test_md5.txt";
- String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
-
- HashCode hash = com.google.common.io.Files.hash(new File(filename), Hashing.md5());
- String myChecksum = hash.toString().toUpperCase();
-
- assertThat(myChecksum.equals(checksum)).isTrue();
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
deleted file mode 100644
index 8e90725c77..0000000000
--- a/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.baeldung.passwordhashing;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-
-public class PBKDF2HasherUnitTest {
-
- private PBKDF2Hasher mPBKDF2Hasher;
-
- @Before
- public void setUp() throws Exception {
- mPBKDF2Hasher = new PBKDF2Hasher();
- }
-
- @Test
- public void givenCorrectMessageAndHash_whenAuthenticated_checkAuthenticationSucceeds() throws Exception {
- String message1 = "password123";
-
- String hash1 = mPBKDF2Hasher.hash(message1.toCharArray());
-
- assertTrue(mPBKDF2Hasher.checkPassword(message1.toCharArray(), hash1));
-
- }
-
- @Test
- public void givenWrongMessage_whenAuthenticated_checkAuthenticationFails() throws Exception {
- String message1 = "password123";
-
- String hash1 = mPBKDF2Hasher.hash(message1.toCharArray());
-
- String wrongPasswordAttempt = "IamWrong";
-
- assertFalse(mPBKDF2Hasher.checkPassword(wrongPasswordAttempt.toCharArray(), hash1));
-
- }
-
-
-}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
deleted file mode 100644
index 3acfb0ba9d..0000000000
--- a/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.baeldung.passwordhashing;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import java.security.SecureRandom;
-
-import static org.junit.Assert.*;
-
-/**
- * Created by PhysicsSam on 06-Sep-18.
- */
-public class SHA512HasherUnitTest {
-
- private SHA512Hasher hasher;
- private SecureRandom secureRandom;
-
- @Before
- public void setUp() throws Exception {
- hasher = new SHA512Hasher();
- secureRandom = new SecureRandom();
- }
-
- @Test
- public void givenSamePasswordAndSalt_whenHashed_checkResultingHashesAreEqual() throws Exception {
-
- byte[] salt = new byte[16];
- secureRandom.nextBytes(salt);
-
- String hash1 = hasher.hash("password", salt);
- String hash2 = hasher.hash("password", salt);
-
- assertEquals(hash1, hash2);
-
- }
-
- @Test
- public void givenSamePasswordAndDifferentSalt_whenHashed_checkResultingHashesNotEqual() throws Exception {
-
- byte[] salt = new byte[16];
- secureRandom.nextBytes(salt);
- String hash1 = hasher.hash("password", salt);
- //generate a second salt
- byte[] secondSalt = new byte[16];
- String hash2 = hasher.hash("password", secondSalt);
-
- assertNotEquals(hash1, hash2);
-
- }
-
- @Test
- public void givenPredefinedHash_whenCorrectAttemptGiven_checkAuthenticationSucceeds() throws Exception {
- byte[] salt = new byte[16];
- secureRandom.nextBytes(salt);
-
- String originalHash = hasher.hash("password123", salt);
-
- assertTrue(hasher.checkPassword(originalHash, "password123", salt));
- }
-
- @Test
- public void givenPredefinedHash_whenIncorrectAttemptGiven_checkAuthenticationFails() throws Exception {
- byte[] salt = new byte[16];
- secureRandom.nextBytes(salt);
-
- String originalHash = hasher.hash("password123", salt);
-
- assertFalse(hasher.checkPassword(originalHash, "password124", salt));
- }
-}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security/src/test/resources/test_md5.txt b/core-java-modules/core-java-security/src/test/resources/test_md5.txt
deleted file mode 100644
index 95d09f2b10..0000000000
--- a/core-java-modules/core-java-security/src/test/resources/test_md5.txt
+++ /dev/null
@@ -1 +0,0 @@
-hello world
\ No newline at end of file
From e2b6b4bc924f860cd2ab7d77ed17ad8e2d969b15 Mon Sep 17 00:00:00 2001
From: sampadawagde
Date: Sat, 28 Mar 2020 16:48:43 +0530
Subject: [PATCH 031/276] JAVA-623: Moved 3 articles to core-java-security-2
---
.../core-java-security-2/README.md | 8 +
.../core-java-security-2/pom.xml | 30 ++++
.../baeldung/hashing/DigestAlgorithms.java | 9 ++
.../baeldung/hashing/Keccak256Hashing.java | 30 ++++
.../com/baeldung/hashing/SHA256Hashing.java | 39 +++++
.../com/baeldung/hashing/SHA3Hashing.java | 45 ++++++
.../com/baeldung/hashing/SHACommonUtils.java | 16 ++
.../passwordhashing/PBKDF2Hasher.java | 149 ++++++++++++++++++
.../passwordhashing/SHA512Hasher.java | 35 ++++
.../passwordhashing/SimplePBKDF2Hasher.java | 18 +++
.../hashing/Keccak256HashingUnitTest.java | 22 +++
.../hashing/SHA256HashingUnitTest.java | 35 ++++
.../baeldung/hashing/SHA3HashingUnitTest.java | 38 +++++
.../baeldung/java/md5/JavaMD5UnitTest.java | 75 +++++++++
.../passwordhashing/PBKDF2HasherUnitTest.java | 41 +++++
.../passwordhashing/SHA512HasherUnitTest.java | 70 ++++++++
.../src/test/resources/test_md5.txt | 1 +
17 files changed, 661 insertions(+)
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/DigestAlgorithms.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/Keccak256Hashing.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA256Hashing.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA3Hashing.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java
create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java
create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java
create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
create mode 100644 core-java-modules/core-java-security-2/src/test/resources/test_md5.txt
diff --git a/core-java-modules/core-java-security-2/README.md b/core-java-modules/core-java-security-2/README.md
index c250e24078..2eb21fb77e 100644
--- a/core-java-modules/core-java-security-2/README.md
+++ b/core-java-modules/core-java-security-2/README.md
@@ -1,3 +1,11 @@
+## Core Java Security
+
+This module contains articles about core Java Security
+
### Relevant Articles:
- [Guide To The Java Authentication And Authorization Service (JAAS)](https://www.baeldung.com/java-authentication-authorization-service)
+- [MD5 Hashing in Java](http://www.baeldung.com/java-md5)
+- [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing)
+- [SHA-256 and SHA3-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java)
+- More articles: [[<-- prev]](/core-java-modules/core-java-security)
diff --git a/core-java-modules/core-java-security-2/pom.xml b/core-java-modules/core-java-security-2/pom.xml
index 23f0c5aab9..9315ab4af2 100644
--- a/core-java-modules/core-java-security-2/pom.xml
+++ b/core-java-modules/core-java-security-2/pom.xml
@@ -16,4 +16,34 @@
../../parent-java
+
+
+ commons-codec
+ commons-codec
+ ${commons-codec.version}
+
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+ ${bouncycastle.version}
+
+
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
+ test
+
+
+
+
+
+ 1.60
+ 1.11
+
+
+ 3.10.0
+
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/DigestAlgorithms.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/DigestAlgorithms.java
new file mode 100644
index 0000000000..94dd22ff4b
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/DigestAlgorithms.java
@@ -0,0 +1,9 @@
+package com.baeldung.hashing;
+
+public class DigestAlgorithms {
+
+ public static final String SHA3_256 = "SHA3-256";
+ public static final String SHA_256 = "SHA-256";
+ public static final String KECCAK_256 = "Keccak-256";
+
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/Keccak256Hashing.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/Keccak256Hashing.java
new file mode 100644
index 0000000000..19fc4cf059
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/Keccak256Hashing.java
@@ -0,0 +1,30 @@
+package com.baeldung.hashing;
+
+import org.bouncycastle.jcajce.provider.digest.Keccak;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.encoders.Hex;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+
+import static com.baeldung.hashing.DigestAlgorithms.KECCAK_256;
+import static com.baeldung.hashing.SHACommonUtils.bytesToHex;
+
+public class Keccak256Hashing {
+
+ public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException {
+ Security.addProvider(new BouncyCastleProvider());
+ final MessageDigest digest = MessageDigest.getInstance(KECCAK_256);
+ final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ return bytesToHex(encodedhash);
+ }
+
+ public static String hashWithBouncyCastle(final String originalString) {
+ Keccak.Digest256 digest256 = new Keccak.Digest256();
+ byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ return new String(Hex.encode(hashbytes));
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA256Hashing.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA256Hashing.java
new file mode 100644
index 0000000000..ec008cebab
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA256Hashing.java
@@ -0,0 +1,39 @@
+package com.baeldung.hashing;
+
+import com.google.common.hash.Hashing;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.bouncycastle.util.encoders.Hex;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import static com.baeldung.hashing.DigestAlgorithms.SHA_256;
+import static com.baeldung.hashing.SHACommonUtils.bytesToHex;
+
+public class SHA256Hashing {
+
+ public static String HashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException {
+ final MessageDigest digest = MessageDigest.getInstance(SHA_256);
+ final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ return bytesToHex(encodedhash);
+ }
+
+ public static String hashWithGuava(final String originalString) {
+ final String sha256hex = Hashing.sha256().hashString(originalString, StandardCharsets.UTF_8).toString();
+ return sha256hex;
+ }
+
+ public static String HashWithApacheCommons(final String originalString) {
+ final String sha256hex = DigestUtils.sha256Hex(originalString);
+ return sha256hex;
+ }
+
+ public static String HashWithBouncyCastle(final String originalString) throws NoSuchAlgorithmException {
+ final MessageDigest digest = MessageDigest.getInstance(SHA_256);
+ final byte[] hash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ final String sha256hex = new String(Hex.encode(hash));
+ return sha256hex;
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA3Hashing.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA3Hashing.java
new file mode 100644
index 0000000000..eb363205b1
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA3Hashing.java
@@ -0,0 +1,45 @@
+package com.baeldung.hashing;
+
+import com.google.common.hash.Hashing;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.bouncycastle.crypto.digests.SHA3Digest;
+import org.bouncycastle.jcajce.provider.digest.SHA3;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.encoders.Hex;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+
+import static com.baeldung.hashing.DigestAlgorithms.SHA3_256;
+import static com.baeldung.hashing.SHACommonUtils.bytesToHex;
+
+public class SHA3Hashing {
+
+ /* works with JDK9+ only */
+ public static String hashWithJavaMessageDigestJDK9(final String originalString) throws NoSuchAlgorithmException {
+ final MessageDigest digest = MessageDigest.getInstance(SHA3_256);
+ final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ return bytesToHex(hashbytes);
+ }
+
+ public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException {
+ Security.addProvider(new BouncyCastleProvider());
+ final MessageDigest digest = MessageDigest.getInstance(SHA3_256);
+ final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ return bytesToHex(hashbytes);
+ }
+
+ /* works with JDK9+ only */
+ public static String hashWithApacheCommonsJDK9(final String originalString) {
+ return new DigestUtils(SHA3_256).digestAsHex(originalString);
+ }
+
+ public static String hashWithBouncyCastle(final String originalString) {
+ SHA3.Digest256 digest256 = new SHA3.Digest256();
+ byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ return new String(Hex.encode(hashbytes));
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java
new file mode 100644
index 0000000000..0f28408083
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java
@@ -0,0 +1,16 @@
+package com.baeldung.hashing;
+
+class SHACommonUtils {
+
+ public static String bytesToHex(byte[] hash) {
+ StringBuffer hexString = new StringBuffer();
+ for (byte h : hash) {
+ String hex = Integer.toHexString(0xff & h);
+ if (hex.length() == 1)
+ hexString.append('0');
+ hexString.append(hex);
+ }
+ return hexString.toString();
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
new file mode 100644
index 0000000000..e2259e4249
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
@@ -0,0 +1,149 @@
+package com.baeldung.passwordhashing;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+/**
+ * Hash passwords for storage, and test passwords against password tokens.
+ *
+ * Instances of this class can be used concurrently by multiple threads.
+ *
+ * @author erickson
+ * @see StackOverflow
+ */
+public final class PBKDF2Hasher
+{
+
+ /**
+ * Each token produced by this class uses this identifier as a prefix.
+ */
+ public static final String ID = "$31$";
+
+ /**
+ * The minimum recommended cost, used by default
+ */
+ public static final int DEFAULT_COST = 16;
+
+ private static final String ALGORITHM = "PBKDF2WithHmacSHA1";
+
+ private static final int SIZE = 128;
+
+ private static final Pattern layout = Pattern.compile("\\$31\\$(\\d\\d?)\\$(.{43})");
+
+ private final SecureRandom random;
+
+ private final int cost;
+
+ public PBKDF2Hasher()
+ {
+ this(DEFAULT_COST);
+ }
+
+ /**
+ * Create a password manager with a specified cost
+ *
+ * @param cost the exponential computational cost of hashing a password, 0 to 30
+ */
+ public PBKDF2Hasher(int cost)
+ {
+ iterations(cost); /* Validate cost */
+ this.cost = cost;
+ this.random = new SecureRandom();
+ }
+
+ private static int iterations(int cost)
+ {
+ if ((cost < 0) || (cost > 30))
+ throw new IllegalArgumentException("cost: " + cost);
+ return 1 << cost;
+ }
+
+ /**
+ * Hash a password for storage.
+ *
+ * @return a secure authentication token to be stored for later authentication
+ */
+ public String hash(char[] password)
+ {
+ byte[] salt = new byte[SIZE / 8];
+ random.nextBytes(salt);
+ byte[] dk = pbkdf2(password, salt, 1 << cost);
+ byte[] hash = new byte[salt.length + dk.length];
+ System.arraycopy(salt, 0, hash, 0, salt.length);
+ System.arraycopy(dk, 0, hash, salt.length, dk.length);
+ Base64.Encoder enc = Base64.getUrlEncoder().withoutPadding();
+ return ID + cost + '$' + enc.encodeToString(hash);
+ }
+
+ /**
+ * Authenticate with a password and a stored password token.
+ *
+ * @return true if the password and token match
+ */
+ public boolean checkPassword(char[] password, String token)
+ {
+ Matcher m = layout.matcher(token);
+ if (!m.matches())
+ throw new IllegalArgumentException("Invalid token format");
+ int iterations = iterations(Integer.parseInt(m.group(1)));
+ byte[] hash = Base64.getUrlDecoder().decode(m.group(2));
+ byte[] salt = Arrays.copyOfRange(hash, 0, SIZE / 8);
+ byte[] check = pbkdf2(password, salt, iterations);
+ int zero = 0;
+ for (int idx = 0; idx < check.length; ++idx)
+ zero |= hash[salt.length + idx] ^ check[idx];
+ return zero == 0;
+ }
+
+ private static byte[] pbkdf2(char[] password, byte[] salt, int iterations)
+ {
+ KeySpec spec = new PBEKeySpec(password, salt, iterations, SIZE);
+ try {
+ SecretKeyFactory f = SecretKeyFactory.getInstance(ALGORITHM);
+ return f.generateSecret(spec).getEncoded();
+ }
+ catch (NoSuchAlgorithmException ex) {
+ throw new IllegalStateException("Missing algorithm: " + ALGORITHM, ex);
+ }
+ catch (InvalidKeySpecException ex) {
+ throw new IllegalStateException("Invalid SecretKeyFactory", ex);
+ }
+ }
+
+ /**
+ * Hash a password in an immutable {@code String}.
+ *
+ * Passwords should be stored in a {@code char[]} so that it can be filled
+ * with zeros after use instead of lingering on the heap and elsewhere.
+ *
+ * @deprecated Use {@link #hash(char[])} instead
+ */
+ @Deprecated
+ public String hash(String password)
+ {
+ return hash(password.toCharArray());
+ }
+
+ /**
+ * Authenticate with a password in an immutable {@code String} and a stored
+ * password token.
+ *
+ * @deprecated Use {@link #checkPassword(char[],String)} instead.
+ * @see #hash(String)
+ */
+ @Deprecated
+ public boolean checkPassword(String password, String token)
+ {
+ return checkPassword(password.toCharArray(), token);
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
new file mode 100644
index 0000000000..4f5337f963
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
@@ -0,0 +1,35 @@
+package com.baeldung.passwordhashing;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+
+/** A really simple SHA_512 Encryption example.
+ *
+ */
+public class SHA512Hasher {
+
+ public String hash(String passwordToHash, byte[] salt){
+ String generatedPassword = null;
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-512");
+ md.update(salt);
+ byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
+ StringBuilder sb = new StringBuilder();
+ for(int i=0; i< bytes.length ;i++){
+ sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
+ }
+ generatedPassword = sb.toString();
+ }
+ catch (NoSuchAlgorithmException e){
+ e.printStackTrace();
+ }
+ return generatedPassword;
+ }
+
+ public boolean checkPassword(String hash, String attempt, byte[] salt){
+ String generatedHash = hash(attempt, salt);
+ return hash.equals(generatedHash);
+ }
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
new file mode 100644
index 0000000000..36c9b65070
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
@@ -0,0 +1,18 @@
+package com.baeldung.passwordhashing;
+
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import java.security.spec.KeySpec;
+
+/** A really simple SimplePBKDF2 Encryption example.
+ *
+ */
+public class SimplePBKDF2Hasher {
+
+ public static String hashSimple(String password, byte[] salt) throws Exception{
+ KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
+ SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
+ byte[] hash = f.generateSecret(spec).getEncoded();
+ return String.valueOf(hash);
+ }
+}
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java
new file mode 100644
index 0000000000..9ed35c8834
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.hashing;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class Keccak256HashingUnitTest {
+
+ private static String originalValue = "abc123";
+ private static String hashedValue = "719accc61a9cc126830e5906f9d672d06eab6f8597287095a2c55a8b775e7016";
+
+ @Test public void testHashWithJavaMessageDigest() throws Exception {
+ final String currentHashedValue = Keccak256Hashing.hashWithJavaMessageDigest(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ @Test public void testHashWithBouncyCastle() {
+ final String currentHashedValue = Keccak256Hashing.hashWithBouncyCastle(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
new file mode 100644
index 0000000000..6bc9ad2cc6
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
@@ -0,0 +1,35 @@
+package com.baeldung.hashing;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class SHA256HashingUnitTest {
+
+ private static String originalValue = "abc123";
+ private static String hashedValue = "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090";
+
+ @Test
+ public void testHashWithJavaMessageDigest() throws Exception {
+ final String currentHashedValue = SHA256Hashing.HashWithJavaMessageDigest(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ @Test
+ public void testHashWithGuava() throws Exception {
+ final String currentHashedValue = SHA256Hashing.hashWithGuava(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ @Test
+ public void testHashWithApacheCommans() throws Exception {
+ final String currentHashedValue = SHA256Hashing.HashWithApacheCommons(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ @Test
+ public void testHashWithBouncyCastle() throws Exception {
+ final String currentHashedValue = SHA256Hashing.HashWithBouncyCastle(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java
new file mode 100644
index 0000000000..fffab96405
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.hashing;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class SHA3HashingUnitTest {
+
+ private static String originalValue = "abc123";
+ private static String hashedValue = "f58fa3df820114f56e1544354379820cff464c9c41cb3ca0ad0b0843c9bb67ee";
+
+ /* works with JDK9+ only */
+ //@Test
+ public void testHashWithJavaMessageDigestJDK9() throws Exception {
+ final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigestJDK9(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ @Test
+ public void testHashWithJavaMessageDigest() throws Exception {
+ final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigest(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ /* works with JDK9+ only */
+ //@Test
+ public void testHashWithApacheCommonsJDK9() {
+ final String currentHashedValue = SHA3Hashing.hashWithApacheCommonsJDK9(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ @Test
+ public void testHashWithBouncyCastle() {
+ final String currentHashedValue = SHA3Hashing.hashWithBouncyCastle(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java
new file mode 100644
index 0000000000..67d6918c09
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java
@@ -0,0 +1,75 @@
+package com.baeldung.java.md5;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.junit.Test;
+
+import com.google.common.hash.HashCode;
+import com.google.common.hash.Hashing;
+
+public class JavaMD5UnitTest {
+
+ String filename = "src/test/resources/test_md5.txt";
+ String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
+
+ String hash = "35454B055CC325EA1AF2126E27707052";
+ String password = "ILoveJava";
+
+ @Test
+ public void givenPassword_whenHashing_thenVerifying() throws NoSuchAlgorithmException {
+ String hash = "35454B055CC325EA1AF2126E27707052";
+ String password = "ILoveJava";
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(password.getBytes());
+ byte[] digest = md.digest();
+ String myHash = DatatypeConverter.printHexBinary(digest).toUpperCase();
+
+ assertThat(myHash.equals(hash)).isTrue();
+ }
+
+ @Test
+ public void givenFile_generatingChecksum_thenVerifying() throws NoSuchAlgorithmException, IOException {
+ String filename = "src/test/resources/test_md5.txt";
+ String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(Files.readAllBytes(Paths.get(filename)));
+ byte[] digest = md.digest();
+ String myChecksum = DatatypeConverter.printHexBinary(digest).toUpperCase();
+
+ assertThat(myChecksum.equals(checksum)).isTrue();
+ }
+
+ @Test
+ public void givenPassword_whenHashingUsingCommons_thenVerifying() {
+ String hash = "35454B055CC325EA1AF2126E27707052";
+ String password = "ILoveJava";
+
+ String md5Hex = DigestUtils.md5Hex(password).toUpperCase();
+
+ assertThat(md5Hex.equals(hash)).isTrue();
+ }
+
+ @Test
+ public void givenFile_whenChecksumUsingGuava_thenVerifying() throws IOException {
+ String filename = "src/test/resources/test_md5.txt";
+ String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
+
+ HashCode hash = com.google.common.io.Files.hash(new File(filename), Hashing.md5());
+ String myChecksum = hash.toString().toUpperCase();
+
+ assertThat(myChecksum.equals(checksum)).isTrue();
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
new file mode 100644
index 0000000000..8e90725c77
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
@@ -0,0 +1,41 @@
+package com.baeldung.passwordhashing;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+public class PBKDF2HasherUnitTest {
+
+ private PBKDF2Hasher mPBKDF2Hasher;
+
+ @Before
+ public void setUp() throws Exception {
+ mPBKDF2Hasher = new PBKDF2Hasher();
+ }
+
+ @Test
+ public void givenCorrectMessageAndHash_whenAuthenticated_checkAuthenticationSucceeds() throws Exception {
+ String message1 = "password123";
+
+ String hash1 = mPBKDF2Hasher.hash(message1.toCharArray());
+
+ assertTrue(mPBKDF2Hasher.checkPassword(message1.toCharArray(), hash1));
+
+ }
+
+ @Test
+ public void givenWrongMessage_whenAuthenticated_checkAuthenticationFails() throws Exception {
+ String message1 = "password123";
+
+ String hash1 = mPBKDF2Hasher.hash(message1.toCharArray());
+
+ String wrongPasswordAttempt = "IamWrong";
+
+ assertFalse(mPBKDF2Hasher.checkPassword(wrongPasswordAttempt.toCharArray(), hash1));
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
new file mode 100644
index 0000000000..3acfb0ba9d
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
@@ -0,0 +1,70 @@
+package com.baeldung.passwordhashing;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.security.SecureRandom;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by PhysicsSam on 06-Sep-18.
+ */
+public class SHA512HasherUnitTest {
+
+ private SHA512Hasher hasher;
+ private SecureRandom secureRandom;
+
+ @Before
+ public void setUp() throws Exception {
+ hasher = new SHA512Hasher();
+ secureRandom = new SecureRandom();
+ }
+
+ @Test
+ public void givenSamePasswordAndSalt_whenHashed_checkResultingHashesAreEqual() throws Exception {
+
+ byte[] salt = new byte[16];
+ secureRandom.nextBytes(salt);
+
+ String hash1 = hasher.hash("password", salt);
+ String hash2 = hasher.hash("password", salt);
+
+ assertEquals(hash1, hash2);
+
+ }
+
+ @Test
+ public void givenSamePasswordAndDifferentSalt_whenHashed_checkResultingHashesNotEqual() throws Exception {
+
+ byte[] salt = new byte[16];
+ secureRandom.nextBytes(salt);
+ String hash1 = hasher.hash("password", salt);
+ //generate a second salt
+ byte[] secondSalt = new byte[16];
+ String hash2 = hasher.hash("password", secondSalt);
+
+ assertNotEquals(hash1, hash2);
+
+ }
+
+ @Test
+ public void givenPredefinedHash_whenCorrectAttemptGiven_checkAuthenticationSucceeds() throws Exception {
+ byte[] salt = new byte[16];
+ secureRandom.nextBytes(salt);
+
+ String originalHash = hasher.hash("password123", salt);
+
+ assertTrue(hasher.checkPassword(originalHash, "password123", salt));
+ }
+
+ @Test
+ public void givenPredefinedHash_whenIncorrectAttemptGiven_checkAuthenticationFails() throws Exception {
+ byte[] salt = new byte[16];
+ secureRandom.nextBytes(salt);
+
+ String originalHash = hasher.hash("password123", salt);
+
+ assertFalse(hasher.checkPassword(originalHash, "password124", salt));
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security-2/src/test/resources/test_md5.txt b/core-java-modules/core-java-security-2/src/test/resources/test_md5.txt
new file mode 100644
index 0000000000..95d09f2b10
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/resources/test_md5.txt
@@ -0,0 +1 @@
+hello world
\ No newline at end of file
From e189686b4a55267a1a0b369ef0f170576b2a0eb7 Mon Sep 17 00:00:00 2001
From: naXa!
Date: Sun, 17 Mar 2019 22:24:10 +0300
Subject: [PATCH 032/276] [BAEL-2749] create new module `dbunit`; add DbUnit
tests: `OldSchoolDbUnitTest` + `PrepAndExpectedDbUnitTest` + relevant data
---
dbunit/README.md | 6 +
dbunit/docs/db_schema.png | Bin 0 -> 17099 bytes
dbunit/pom.xml | 35 ++++++
.../main/java/com/baeldung/dbunit/.gitkeep | 0
dbunit/src/main/resources/logback.xml | 13 ++
.../baeldung/dbunit/OldSchoolDbUnitTest.java | 111 ++++++++++++++++++
.../dbunit/PrepAndExpectedDbUnitTest.java | 103 ++++++++++++++++
dbunit/src/test/resources/data.xml | 11 ++
dbunit/src/test/resources/items.xml | 9 ++
.../src/test/resources/items_exp_delete.xml | 8 ++
.../src/test/resources/items_exp_rename.xml | 9 ++
dbunit/src/test/resources/schema.sql | 28 +++++
dbunit/src/test/resources/users.xml | 7 ++
.../src/test/resources/users_exp_delete.xml | 6 +
.../src/test/resources/users_exp_rename.xml | 7 ++
15 files changed, 353 insertions(+)
create mode 100644 dbunit/README.md
create mode 100644 dbunit/docs/db_schema.png
create mode 100644 dbunit/pom.xml
create mode 100644 dbunit/src/main/java/com/baeldung/dbunit/.gitkeep
create mode 100644 dbunit/src/main/resources/logback.xml
create mode 100644 dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
create mode 100644 dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
create mode 100644 dbunit/src/test/resources/data.xml
create mode 100644 dbunit/src/test/resources/items.xml
create mode 100644 dbunit/src/test/resources/items_exp_delete.xml
create mode 100644 dbunit/src/test/resources/items_exp_rename.xml
create mode 100644 dbunit/src/test/resources/schema.sql
create mode 100644 dbunit/src/test/resources/users.xml
create mode 100644 dbunit/src/test/resources/users_exp_delete.xml
create mode 100644 dbunit/src/test/resources/users_exp_rename.xml
diff --git a/dbunit/README.md b/dbunit/README.md
new file mode 100644
index 0000000000..383bd6fb7e
--- /dev/null
+++ b/dbunit/README.md
@@ -0,0 +1,6 @@
+### Database schema
+
+
+
+### Relevant Articles:
+- [Introduction To DBUnit](https://www.baeldung.com/dbunit)
diff --git a/dbunit/docs/db_schema.png b/dbunit/docs/db_schema.png
new file mode 100644
index 0000000000000000000000000000000000000000..d9185bacd2c624c8e05aea87bf542cfdfd7f1604
GIT binary patch
literal 17099
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 5+_56s{#5ostk#`d
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
+ 4.0.0
+ dbunit
+ 1.0
+ dbunit
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.dbunit
+ dbunit
+ ${dbunit.version}
+ test
+
+
+
+ com.h2database
+ h2
+ 1.4.197
+ test
+
+
+
+
+
+ 2.6.0
+
+
+
diff --git a/dbunit/src/main/java/com/baeldung/dbunit/.gitkeep b/dbunit/src/main/java/com/baeldung/dbunit/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/dbunit/src/main/resources/logback.xml b/dbunit/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/dbunit/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
new file mode 100644
index 0000000000..a703863614
--- /dev/null
+++ b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
@@ -0,0 +1,111 @@
+package com.baeldung.dbunit;
+
+import org.dbunit.Assertion;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.JdbcDatabaseTester;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.ITable;
+import org.dbunit.dataset.xml.FlatXmlDataSet;
+import org.dbunit.operation.DatabaseOperation;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.ResultSet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class OldSchoolDbUnitTest {
+ private static final String JDBC_DRIVER = org.h2.Driver.class.getName();
+ private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'";
+ private static final String USER = "sa";
+ private static final String PASSWORD = "";
+
+ private static IDatabaseTester tester = null;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ tester = initDatabaseTester();
+ }
+
+ private static IDatabaseTester initDatabaseTester() throws Exception {
+ final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD);
+ tester.setDataSet(initDataSet());
+ tester.setSetUpOperation(DatabaseOperation.REFRESH);
+ tester.setTearDownOperation(DatabaseOperation.NONE);
+ return tester;
+ }
+
+ private static IDataSet initDataSet() throws Exception {
+ final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("data.xml");
+ return new FlatXmlDataSet(is);
+ }
+
+ @Before
+ public void setup() throws Exception {
+ tester.onSetup();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ tester.onTearDown();
+ }
+
+ @Test
+ public void testSelect() throws Exception {
+ // Arrange
+ final Connection connection = tester.getConnection().getConnection();
+
+ // Act
+ final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1");
+
+ // Assert
+ assertTrue(rs.next());
+ assertEquals("Grey T-Shirt", rs.getString("title"));
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ // Arrange
+ final Connection connection = tester.getConnection().getConnection();
+
+ final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml");
+ ITable expectedTable = (new FlatXmlDataSet(is)).getTable("items");
+ //expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"produced"});
+
+ // Act
+ connection.createStatement().executeUpdate("delete from ITEMS where id = 2");
+
+ // Assert
+ final IDataSet databaseDataSet = tester.getConnection().createDataSet();
+ ITable actualTable = databaseDataSet.getTable("items");
+ //actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"});
+
+ Assertion.assertEquals(expectedTable, actualTable);
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ // Arrange
+ final Connection connection = tester.getConnection().getConnection();
+
+ final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml");
+ ITable expectedTable = (new FlatXmlDataSet(is)).getTable("items");
+ //expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"produced"});
+
+ // Act
+ connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1");
+
+ // Assert
+ final IDataSet databaseDataSet = tester.getConnection().createDataSet();
+ ITable actualTable = databaseDataSet.getTable("items");
+ //actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"});
+
+ Assertion.assertEquals(expectedTable, actualTable);
+ }
+
+}
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
new file mode 100644
index 0000000000..c3882d5eab
--- /dev/null
+++ b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
@@ -0,0 +1,103 @@
+package com.baeldung.dbunit;
+
+import org.dbunit.*;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
+import org.dbunit.operation.DatabaseOperation;
+import org.dbunit.util.fileloader.DataFileLoader;
+import org.dbunit.util.fileloader.FlatXmlDataFileLoader;
+import org.junit.Test;
+
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.ResultSet;
+
+public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase {
+ private static final String JDBC_DRIVER = org.h2.Driver.class.getName();
+ private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'";
+ private static final String USER = "sa";
+ private static final String PASSWORD = "";
+
+ @Override
+ public void setUp() throws Exception {
+ setDatabaseTester(initDatabaseTester());
+ setDataFileLoader(initDataFileLoader());
+ super.setUp();
+ }
+
+ private IDatabaseTester initDatabaseTester() throws Exception {
+ final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD);
+ tester.setDataSet(initDataSet());
+ tester.setSetUpOperation(DatabaseOperation.REFRESH);
+ return tester;
+ }
+
+ private IDataSet initDataSet() throws Exception {
+ final InputStream is = getClass().getClassLoader().getResourceAsStream("data.xml");
+ return new FlatXmlDataSetBuilder().build(is);
+ }
+
+ private DataFileLoader initDataFileLoader() {
+ return new FlatXmlDataFileLoader();
+ }
+
+ @Test
+ public void testSelect() throws Exception {
+ // Arrange
+ final Connection connection = getConnection().getConnection();
+ final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})};
+ final String[] prepDataFiles = {"/users.xml"};
+ final String[] expectedDataFiles = {"/users.xml"};
+ final PrepAndExpectedTestCaseSteps testSteps = () -> {
+ // invoke the method being tested here; for the sake of simplicity we use JDBC API directly in this example
+ final ResultSet rs = connection.createStatement().executeQuery("select * from USERS where id = 1");
+
+ // either place assertions here
+ //assertTrue(rs.next());
+ //assertEquals("Xavier", rs.getString("last_name"));
+
+ return rs;
+ };
+
+ // Act
+ final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps);
+
+ // or place assertions at the end
+ assertTrue(rs.next());
+ assertEquals("Xavier", rs.getString("last_name"));
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ // Arrange
+ final Connection connection = getConnection().getConnection();
+ final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})}; // define tables to verify
+ final String[] prepDataFiles = {"/users.xml"}; // define prep files
+ final String[] expectedDataFiles = {"/users_exp_rename.xml"}; // define expected files
+ final PrepAndExpectedTestCaseSteps testSteps = () -> {
+ // invoke the method being tested here; for the sake of simplicity we use JDBC API directly in this example
+ return connection.createStatement().executeUpdate("update USERS set first_name = 'new name' where id = 1");
+ // after this method exits, dbUnit will:
+ // * verify configured tables
+ // * cleanup tables as configured
+ };
+
+ // Act
+ super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps);
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ // Arrange
+ final Connection connection = getConnection().getConnection();
+ final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})};
+ final String[] prepDataFiles = {"/users.xml"};
+ final String[] expectedDataFiles = {"/users_exp_delete.xml"};
+ final PrepAndExpectedTestCaseSteps testSteps =
+ () -> connection.createStatement().executeUpdate("delete from USERS where id = 2");
+
+ // Act
+ super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps);
+ }
+
+}
diff --git a/dbunit/src/test/resources/data.xml b/dbunit/src/test/resources/data.xml
new file mode 100644
index 0000000000..e4498513e0
--- /dev/null
+++ b/dbunit/src/test/resources/data.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dbunit/src/test/resources/items.xml b/dbunit/src/test/resources/items.xml
new file mode 100644
index 0000000000..04a975d7ee
--- /dev/null
+++ b/dbunit/src/test/resources/items.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/dbunit/src/test/resources/items_exp_delete.xml b/dbunit/src/test/resources/items_exp_delete.xml
new file mode 100644
index 0000000000..1aaeff59ca
--- /dev/null
+++ b/dbunit/src/test/resources/items_exp_delete.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/dbunit/src/test/resources/items_exp_rename.xml b/dbunit/src/test/resources/items_exp_rename.xml
new file mode 100644
index 0000000000..237280e758
--- /dev/null
+++ b/dbunit/src/test/resources/items_exp_rename.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/dbunit/src/test/resources/schema.sql b/dbunit/src/test/resources/schema.sql
new file mode 100644
index 0000000000..9b5018985a
--- /dev/null
+++ b/dbunit/src/test/resources/schema.sql
@@ -0,0 +1,28 @@
+CREATE TABLE IF NOT EXISTS USERS
+(
+ `id` int AUTO_INCREMENT NOT NULL,
+ `first_name` varchar(100) NOT NULL,
+ `last_name` varchar(100) NOT NULL,
+ PRIMARY KEY (`id`)
+);
+
+CREATE TABLE IF NOT EXISTS ITEMS
+(
+ `id` int AUTO_INCREMENT NOT NULL,
+ `title` varchar(100) NOT NULL,
+ `produced` date,
+ `price` float,
+ PRIMARY KEY (`id`)
+);
+
+CREATE TABLE IF NOT EXISTS PURCHASES
+(
+ `id` int NOT NULL AUTO_INCREMENT,
+ `id_user` int NOT NULL,
+ `id_item` int NOT NULL,
+ `total_price` float NOT NULL,
+ `quantity` int(11) NOT NULL,
+ PRIMARY KEY (`id`),
+ FOREIGN KEY (`id_user`) REFERENCES USERS (`id`) ON DELETE CASCADE,
+ FOREIGN KEY (`id_item`) REFERENCES ITEMS (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+);
diff --git a/dbunit/src/test/resources/users.xml b/dbunit/src/test/resources/users.xml
new file mode 100644
index 0000000000..cebadf2e67
--- /dev/null
+++ b/dbunit/src/test/resources/users.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/dbunit/src/test/resources/users_exp_delete.xml b/dbunit/src/test/resources/users_exp_delete.xml
new file mode 100644
index 0000000000..8b72ceef89
--- /dev/null
+++ b/dbunit/src/test/resources/users_exp_delete.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/dbunit/src/test/resources/users_exp_rename.xml b/dbunit/src/test/resources/users_exp_rename.xml
new file mode 100644
index 0000000000..9bc1254967
--- /dev/null
+++ b/dbunit/src/test/resources/users_exp_rename.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
From 6194165f0d1c57ef5d6b5f1111d96107beee735c Mon Sep 17 00:00:00 2001
From: naXa!
Date: Mon, 25 Mar 2019 01:37:05 +0300
Subject: [PATCH 033/276] [BAEL-2749] add `SampleDbUnitTest` (extending
`DBTestCase`)
---
.../com/baeldung/dbunit/SampleDbUnitTest.java | 96 +++++++++++++++++++
1 file changed, 96 insertions(+)
create mode 100644 dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java
new file mode 100644
index 0000000000..cfe4fd4e11
--- /dev/null
+++ b/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java
@@ -0,0 +1,96 @@
+package com.baeldung.dbunit;
+
+import org.dbunit.Assertion;
+import org.dbunit.DBTestCase;
+import org.dbunit.PropertiesBasedJdbcDatabaseTester;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.ITable;
+import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
+import org.dbunit.operation.DatabaseOperation;
+import org.junit.Test;
+
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.ResultSet;
+
+public class SampleDbUnitTest extends DBTestCase {
+ private static final String JDBC_DRIVER = org.h2.Driver.class.getName();
+ private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'";
+ private static final String USER = "sa";
+ private static final String PASSWORD = "";
+
+ public SampleDbUnitTest(String name) {
+ super(name);
+ System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, JDBC_DRIVER);
+ System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL);
+ System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, USER);
+ System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, PASSWORD);
+ // System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_SCHEMA, "");
+ }
+
+ @Override
+ protected IDataSet getDataSet() throws Exception {
+ final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("data.xml");
+ return new FlatXmlDataSetBuilder().build(is);
+ }
+
+ @Override
+ protected DatabaseOperation getSetUpOperation() {
+ return DatabaseOperation.REFRESH;
+ }
+
+ @Override
+ protected DatabaseOperation getTearDownOperation() {
+ return DatabaseOperation.NONE;
+ }
+
+ @Test
+ public void testSelect() throws Exception {
+ // Arrange
+ final Connection connection = getConnection().getConnection();
+
+ // Act
+ final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1");
+
+ // Assert
+ assertTrue(rs.next());
+ assertEquals("Grey T-Shirt", rs.getString("title"));
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ // Arrange
+ final Connection connection = getConnection().getConnection();
+
+ final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml");
+ ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items");
+
+ // Act
+ connection.createStatement().executeUpdate("delete from ITEMS where id = 2");
+
+ // Assert
+ final IDataSet databaseDataSet = getConnection().createDataSet();
+ ITable actualTable = databaseDataSet.getTable("items");
+
+ Assertion.assertEquals(expectedTable, actualTable);
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ // Arrange
+ final Connection connection = getConnection().getConnection();
+
+ final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml");
+ ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items");
+
+ // Act
+ connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1");
+
+ // Assert
+ final IDataSet databaseDataSet = getConnection().createDataSet();
+ ITable actualTable = databaseDataSet.getTable("items");
+
+ Assertion.assertEquals(expectedTable, actualTable);
+ }
+
+}
From 71fecd658963941c694f0528e981b2f88441999d Mon Sep 17 00:00:00 2001
From: Philippe
Date: Sun, 29 Mar 2020 11:49:46 -0300
Subject: [PATCH 034/276] [BAEL-3793][BAEL-3935] Code snippets
---
terraform/best-practices/README.md | 10 +++
.../best-practices/ec2-simple/.gitignore | 4 ++
terraform/best-practices/ec2-simple/SETUP.md | 23 +++++++
terraform/best-practices/ec2-simple/main.tf | 33 +++++++++
.../best-practices/ec2-simple/providers.tf | 6 ++
.../best-practices/ec2-simple/variables.tf | 15 ++++
terraform/best-practices/k8s-basic/.gitignore | 4 ++
terraform/best-practices/k8s-basic/SETUP.md | 15 ++++
terraform/best-practices/k8s-basic/main.tf | 12 ++++
.../best-practices/k8s-basic/providers.tf | 6 ++
.../best-practices/k8s-basic/variables.tf | 9 +++
.../best-practices/k8s-modules/.gitignore | 4 ++
terraform/best-practices/k8s-modules/SETUP.md | 21 ++++++
terraform/best-practices/k8s-modules/main.tf | 27 ++++++++
.../k8s-modules/modules/SvcCustomer/main.tf | 68 ++++++++++++++++++
.../modules/SvcCustomer/outputs.tf | 3 +
.../modules/SvcCustomer/variables.tf | 5 ++
.../k8s-modules/modules/SvcFeedback/main.tf | 69 +++++++++++++++++++
.../modules/SvcFeedback/outputs.tf | 3 +
.../modules/SvcFeedback/variables.tf | 5 ++
.../ingress/www.petshop.com.br/main.tf | 41 +++++++++++
.../ingress/www.petshop.com.br/outputs.tf | 5 ++
.../ingress/www.petshop.com.br/variables.tf | 20 ++++++
.../best-practices/k8s-modules/provider.tf | 13 ++++
terraform/hello-terraform/.gitignore | 6 ++
terraform/hello-terraform/main.tf | 7 ++
26 files changed, 434 insertions(+)
create mode 100644 terraform/best-practices/README.md
create mode 100644 terraform/best-practices/ec2-simple/.gitignore
create mode 100644 terraform/best-practices/ec2-simple/SETUP.md
create mode 100644 terraform/best-practices/ec2-simple/main.tf
create mode 100644 terraform/best-practices/ec2-simple/providers.tf
create mode 100644 terraform/best-practices/ec2-simple/variables.tf
create mode 100644 terraform/best-practices/k8s-basic/.gitignore
create mode 100644 terraform/best-practices/k8s-basic/SETUP.md
create mode 100644 terraform/best-practices/k8s-basic/main.tf
create mode 100644 terraform/best-practices/k8s-basic/providers.tf
create mode 100644 terraform/best-practices/k8s-basic/variables.tf
create mode 100644 terraform/best-practices/k8s-modules/.gitignore
create mode 100644 terraform/best-practices/k8s-modules/SETUP.md
create mode 100644 terraform/best-practices/k8s-modules/main.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf
create mode 100644 terraform/best-practices/k8s-modules/provider.tf
create mode 100644 terraform/hello-terraform/.gitignore
create mode 100644 terraform/hello-terraform/main.tf
diff --git a/terraform/best-practices/README.md b/terraform/best-practices/README.md
new file mode 100644
index 0000000000..fd488b1afb
--- /dev/null
+++ b/terraform/best-practices/README.md
@@ -0,0 +1,10 @@
+# Terraform Sample Code
+
+This folder contains Terraform project samples that illustrates topics covered in the
+"Best practices when using Terraform" article. Setup instructions are available in each sample's folder.
+
+List of available samples:
+
+ * k8s-basic: "Hello world" project that just connects to a Kubernetes cluster and create a new namespace.
+ * ec2-basic: "Hello world" project that creates a single EC2 instance
+ * k8s-modules: A more elaborate sample that creates a simple set of services in a Kubernetes cluster
diff --git a/terraform/best-practices/ec2-simple/.gitignore b/terraform/best-practices/ec2-simple/.gitignore
new file mode 100644
index 0000000000..a70da3ca16
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/.gitignore
@@ -0,0 +1,4 @@
+*.tfvars
+*.tfstate
+*.tfstate.backup
+.terraform
diff --git a/terraform/best-practices/ec2-simple/SETUP.md b/terraform/best-practices/ec2-simple/SETUP.md
new file mode 100644
index 0000000000..3f906b6933
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/SETUP.md
@@ -0,0 +1,23 @@
+# EC2 Basic Sample
+
+This Terraform sample project creates a single EC2 instance in the configured region.
+
+IMPORTANT NOTICE: In order to run this sample you must have an active AWS Account. As you probably know, creating resources on AWS
+may result in additional charges in your bill. We recommend creating a test account to run this test as you can then use AWS's free tier
+to play around. When finished, ALWAYS REMEMBER TO DESTROY YOUR RESOURCES !!!
+
+# Setup instructions
+
+1. Make sure you have a working AWS environment. Use a simple command such as _aws ec2 describe-instances_ and check its output.
+ If you get a list of existing EC2 instances, you're good to go. Otherwise, please refer to AWS documentation in order to setup your CLI.
+2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere
+ in the OS's PATH.
+3. Open a command prompt and _cd_ into this folder
+4. Run the following commands:
+'''
+ $ terraform init
+ $ terraform apply -auto-approve
+'''
+5. Wait until Terraform create all resources and run _aws ec2 describe-instances_. The output should list the newly creates EC2 instance
+6. Run _terraform destroy_ to remove the previously creates namespace.
+
diff --git a/terraform/best-practices/ec2-simple/main.tf b/terraform/best-practices/ec2-simple/main.tf
new file mode 100644
index 0000000000..57fb9d1757
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/main.tf
@@ -0,0 +1,33 @@
+#
+# Resource definitions
+#
+
+data "aws_ami" "apache" {
+ filter {
+ name = "name"
+ values = [var.ami_name]
+ }
+
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+
+ owners = [var.ami_owner]
+
+ most_recent = true
+}
+
+resource "aws_instance" "web" {
+ ami = data.aws_ami.apache.id
+ instance_type = "t2.micro"
+ subnet_id = aws_subnet.frontend.id
+}
+resource "aws_subnet" "frontend" {
+ vpc_id = aws_vpc.apps.id
+ cidr_block = "10.0.1.0/24"
+}
+
+resource "aws_vpc" "apps" {
+ cidr_block = "10.0.0.0/16"
+}
diff --git a/terraform/best-practices/ec2-simple/providers.tf b/terraform/best-practices/ec2-simple/providers.tf
new file mode 100644
index 0000000000..fa5826b067
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/providers.tf
@@ -0,0 +1,6 @@
+#
+# Providers definitions
+#
+provider "aws" {
+ version = "~> 2.53"
+}
\ No newline at end of file
diff --git a/terraform/best-practices/ec2-simple/variables.tf b/terraform/best-practices/ec2-simple/variables.tf
new file mode 100644
index 0000000000..2a7fddcd33
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/variables.tf
@@ -0,0 +1,15 @@
+#
+# Variables
+#
+
+variable "ami_name" {
+ type = string
+ description = "AMI name to use for our EC2 instance. Defaults to Ubuntu 18.04 (Bionic)"
+ default = "ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-*"
+}
+
+variable "ami_owner" {
+ type = string
+ description = "AMI Owner ID to use for our EC2 instance. Defaults to 099720109477 (Canonical)"
+ default = "099720109477"
+}
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-basic/.gitignore b/terraform/best-practices/k8s-basic/.gitignore
new file mode 100644
index 0000000000..a70da3ca16
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/.gitignore
@@ -0,0 +1,4 @@
+*.tfvars
+*.tfstate
+*.tfstate.backup
+.terraform
diff --git a/terraform/best-practices/k8s-basic/SETUP.md b/terraform/best-practices/k8s-basic/SETUP.md
new file mode 100644
index 0000000000..479bb75274
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/SETUP.md
@@ -0,0 +1,15 @@
+# Setup instructions
+
+1. Mak sure you have a working Kubernetes environment. Use a simple command such as _kubectl get nodes_ and check its output.
+ If you get a list of nodes that contains at least one _ready_ module, you're good to go
+2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere
+ in the OS's PATH.
+3. Open a command prompt and _cd_ into this folder
+4. Run the following commands:
+'''
+ $ terraform init
+ $ terraform apply -auto-approve
+'''
+5. Wait until Terraform create all resources and run _kubectl get namespaces_. The output should now have a new "hello-terraform" namespace.
+6. Run _terraform destroy_ to remove the previously creates namespace.
+
diff --git a/terraform/best-practices/k8s-basic/main.tf b/terraform/best-practices/k8s-basic/main.tf
new file mode 100644
index 0000000000..5eb3749930
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/main.tf
@@ -0,0 +1,12 @@
+#
+# Resource definitions
+#
+
+resource "kubernetes_namespace" "hello" {
+ metadata {
+ labels = {
+ terraform = "true"
+ }
+ name = var.namespace_name
+ }
+}
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-basic/providers.tf b/terraform/best-practices/k8s-basic/providers.tf
new file mode 100644
index 0000000000..385f857a11
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/providers.tf
@@ -0,0 +1,6 @@
+#
+# Providers definitions
+#
+provider "kubernetes" {
+ version = "~> 1.11"
+}
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-basic/variables.tf b/terraform/best-practices/k8s-basic/variables.tf
new file mode 100644
index 0000000000..b9217079bf
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/variables.tf
@@ -0,0 +1,9 @@
+#
+# Variables
+#
+
+variable "namespace_name" {
+ type = string
+ description = "Name to use for the created namespace"
+ default = "hello-terraform"
+}
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/.gitignore b/terraform/best-practices/k8s-modules/.gitignore
new file mode 100644
index 0000000000..a70da3ca16
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/.gitignore
@@ -0,0 +1,4 @@
+*.tfvars
+*.tfstate
+*.tfstate.backup
+.terraform
diff --git a/terraform/best-practices/k8s-modules/SETUP.md b/terraform/best-practices/k8s-modules/SETUP.md
new file mode 100644
index 0000000000..b7e4c2764d
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/SETUP.md
@@ -0,0 +1,21 @@
+# Kubernetes multimodule sample
+
+This sample deploys two services behind a Kubernetes ingress.
+
+# Setup instructions
+
+1. Mak sure you have a working Kubernetes environment. Use a simple command such as _kubectl get nodes_ and check its output.
+ If you get a list of nodes that contains at least one _ready_ module, you're good to go
+2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere
+ in the OS's PATH.
+3. Open a command prompt and _cd_ into this folder
+4. Run the following commands:
+'''
+ $ terraform init
+ $ terraform apply -auto-approve
+'''
+5. Wait until Terraform create all resources and run _kubectl get services_. The output should now have a few services.
+6. Run _terraform destroy_ to remove the previously creates namespace.
+
+
+
diff --git a/terraform/best-practices/k8s-modules/main.tf b/terraform/best-practices/k8s-modules/main.tf
new file mode 100644
index 0000000000..86426b33db
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/main.tf
@@ -0,0 +1,27 @@
+/*
+ * Top-level definitions
+ */
+
+//================================================================== Ingress
+
+module "ingress_www_petshop_com_br" {
+ source = "./modules/ingress/www.petshop.com.br"
+ ingress_host = "www.petshop.com.br"
+}
+
+//================================================================== Deployments
+
+module "SvcCustomer" {
+ source = "./modules/SvcCustomer"
+}
+
+module "SvcFeedback" {
+ source = "./modules/SvcFeedback"
+}
+
+
+
+
+
+
+
diff --git a/terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf b/terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf
new file mode 100644
index 0000000000..1ca0c91545
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf
@@ -0,0 +1,68 @@
+/*
+ * SvcCustomer deployment resources
+ */
+
+resource "kubernetes_deployment" "SvcCustomer" {
+
+ metadata {
+ name = "svccustomer"
+ labels = {
+ app = "SvcCustomer"
+ }
+ }
+
+ spec {
+ replicas = 1
+
+ selector {
+ match_labels = {
+ app = "SvcCustomer"
+ }
+ }
+
+ template {
+ metadata {
+ labels = {
+ app = "SvcCustomer"
+ }
+ }
+
+ spec {
+ image_pull_secrets {
+ name = "docker-config"
+ }
+
+
+ container {
+ image = "inanimate/echo-server"
+ name = "svccustomer-httpd"
+ env {
+ name = "PORT"
+ value = "80"
+ }
+ }
+ }
+ }
+ }
+}
+
+resource "kubernetes_service" "SvcCustomer" {
+ metadata {
+ name = "svccustomer"
+ }
+
+ spec {
+
+ selector = {
+ app = "SvcCustomer"
+ }
+
+ session_affinity = "ClientIP"
+ port {
+ port = 80
+ }
+
+ //type = "LoadBalancer"
+ }
+ }
+
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf b/terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf
new file mode 100644
index 0000000000..8a37fdf375
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf
@@ -0,0 +1,3 @@
+/*
+ * SvcCustomer output values
+ */
diff --git a/terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf b/terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf
new file mode 100644
index 0000000000..3dfcfcd264
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf
@@ -0,0 +1,5 @@
+/*
+ * SvcCustomer deployment variables
+ */
+
+
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf b/terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf
new file mode 100644
index 0000000000..0f84c9163e
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf
@@ -0,0 +1,69 @@
+/*
+ * SvcFeedback deployment resources
+ */
+
+resource "kubernetes_deployment" "SvcFeedback" {
+
+ metadata {
+ name = "svcfeedback"
+ labels = {
+ app = "SvcFeedback"
+ }
+ }
+
+ spec {
+ replicas = 1
+
+ selector {
+ match_labels = {
+ app = "SvcFeedback"
+ }
+ }
+
+ template {
+ metadata {
+ labels = {
+ app = "SvcFeedback"
+ }
+ }
+
+ spec {
+ image_pull_secrets {
+ name = "docker-config"
+ }
+
+
+ container {
+ image = "inanimate/echo-server"
+ name = "svcfeedback-httpd"
+ env {
+ name = "PORT"
+ value = "80"
+ }
+ }
+
+ }
+ }
+ }
+}
+
+resource "kubernetes_service" "SvcFeedback" {
+ metadata {
+ name = "svcfeedback"
+ }
+
+ spec {
+
+ selector = {
+ app = "SvcFeedback"
+ }
+
+ session_affinity = "ClientIP"
+ port {
+ port = 80
+ }
+
+ //type = "LoadBalancer"
+ }
+ }
+
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf b/terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf
new file mode 100644
index 0000000000..e08c17d4b4
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf
@@ -0,0 +1,3 @@
+/*
+ * SvcFeedback output values
+ */
diff --git a/terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf b/terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf
new file mode 100644
index 0000000000..d8076d41a4
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf
@@ -0,0 +1,5 @@
+/*
+ * SvcFeedback deployment variables
+ */
+
+
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf
new file mode 100644
index 0000000000..0dbda48981
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf
@@ -0,0 +1,41 @@
+/*
+ * Kubernetes Ingress module
+ */
+locals {
+ iname = var.ingress_name == "" ? join("-",["ingress",sha1(uuid())]) : var.ingress_name
+}
+
+resource "kubernetes_ingress" "ingress" {
+ metadata {
+ name = local.iname
+ annotations = map(
+ "nginx.ingress.kubernetes.io/rewrite-target","/"
+ )
+ }
+ spec {
+ rule {
+ http {
+ path {
+ backend {
+ service_name = "svccustomer"
+ service_port = 80
+ }
+ path = "/customers"
+ }
+ path {
+ backend {
+ service_name = "svcfeedback"
+ service_port = 80
+ }
+ path = "/feedback"
+ }
+ }
+ }
+/*
+ tls {
+ secret_name = "tls-secret"
+ }
+*/
+ }
+}
+
diff --git a/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf
new file mode 100644
index 0000000000..e604417b05
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf
@@ -0,0 +1,5 @@
+/*
+ * Output variables
+ */
+
+
diff --git a/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf
new file mode 100644
index 0000000000..9b06128ec5
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf
@@ -0,0 +1,20 @@
+/*
+ * Kubernetes Ingress module
+ */
+
+
+variable "ingress_name" {
+ type = string
+ description = "Ingress name. Defaults to a random name."
+ default = ""
+}
+
+variable "ingress_host" {
+ type = string
+ description = "Ingress hostname"
+ default = "www.petshop.com.br"
+}
+
+
+
+
diff --git a/terraform/best-practices/k8s-modules/provider.tf b/terraform/best-practices/k8s-modules/provider.tf
new file mode 100644
index 0000000000..bb90d66ecf
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/provider.tf
@@ -0,0 +1,13 @@
+#
+# Provider configurations
+# This file will *NOT* be overwriten upon regeneration, so it's safe
+# to add your own customizations
+#
+
+provider "kubernetes" {
+ version = "~> 1.10"
+}
+
+provider "random" {
+ version = "~> 2.2"
+}
\ No newline at end of file
diff --git a/terraform/hello-terraform/.gitignore b/terraform/hello-terraform/.gitignore
new file mode 100644
index 0000000000..452502c50f
--- /dev/null
+++ b/terraform/hello-terraform/.gitignore
@@ -0,0 +1,6 @@
+*.tfvars
+*.tfstate
+*.tfstate.backup
+.terraform
+hello.txt
+
diff --git a/terraform/hello-terraform/main.tf b/terraform/hello-terraform/main.tf
new file mode 100644
index 0000000000..d6a726fa36
--- /dev/null
+++ b/terraform/hello-terraform/main.tf
@@ -0,0 +1,7 @@
+provider "local" {
+ version = "~> 1.4"
+}
+resource "local_file" "hello" {
+ content = "Hello, Terraform"
+ filename = "hello.txt"
+}
From 4382852a1731d9d06f838219ec176ddf89c04d3d Mon Sep 17 00:00:00 2001
From: Krzysiek
Date: Sun, 29 Mar 2020 19:00:40 +0200
Subject: [PATCH 035/276] JAVA-43: Upgrade spring-security-modules to Spring
Boot 2
---
spring-security-modules/spring-security-acl/pom.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/spring-security-modules/spring-security-acl/pom.xml b/spring-security-modules/spring-security-acl/pom.xml
index 3c613f9d92..5c04aaa9ca 100644
--- a/spring-security-modules/spring-security-acl/pom.xml
+++ b/spring-security-modules/spring-security-acl/pom.xml
@@ -10,9 +10,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../../parent-boot-1
+ ../../parent-boot-2
From 35bbf9c8845c7c6091afdefb5fb49e8f54035f1c Mon Sep 17 00:00:00 2001
From: Ali Dehghani
Date: Mon, 30 Mar 2020 01:29:02 +0430
Subject: [PATCH 036/276] Borrowing one Example from JCIP
---
.../volatilekeyword/TaskRunner.java | 25 +++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/volatilekeyword/TaskRunner.java
diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/volatilekeyword/TaskRunner.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/volatilekeyword/TaskRunner.java
new file mode 100644
index 0000000000..f0493d4911
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/volatilekeyword/TaskRunner.java
@@ -0,0 +1,25 @@
+package com.baeldung.concurrent.volatilekeyword;
+
+public class TaskRunner {
+
+ private static int number;
+ private volatile static boolean ready;
+
+ private static class Reader extends Thread {
+
+ @Override
+ public void run() {
+ while (!ready) {
+ Thread.yield();
+ }
+
+ System.out.println(number);
+ }
+ }
+
+ public static void main(String[] args) {
+ new Reader().start();
+ number = 42;
+ ready = true;
+ }
+}
From ee95317ad9dd8af56a885bcac40b9b11d04dca56 Mon Sep 17 00:00:00 2001
From: Krzysiek
Date: Sun, 29 Mar 2020 23:54:31 +0200
Subject: [PATCH 037/276] JAVA-42: Upgrade spring-security-ldap to Spring Boot
2
---
.../spring-security-ldap/pom.xml | 8 +++++--
.../com/baeldung/SampleLDAPApplication.java | 13 +-----------
.../{security => config}/SecurityConfig.java | 21 +++++++++++++++----
.../java/com/baeldung/config/WebConfig.java | 16 ++++++++++++++
.../src/main/resources/application.properties | 1 +
.../src/main/resources/webSecurityConfig.xml | 1 +
6 files changed, 42 insertions(+), 18 deletions(-)
rename spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/{security => config}/SecurityConfig.java (53%)
create mode 100644 spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/config/WebConfig.java
create mode 100644 spring-security-modules/spring-security-ldap/src/main/resources/application.properties
diff --git a/spring-security-modules/spring-security-ldap/pom.xml b/spring-security-modules/spring-security-ldap/pom.xml
index f5e8856648..baed682186 100644
--- a/spring-security-modules/spring-security-ldap/pom.xml
+++ b/spring-security-modules/spring-security-ldap/pom.xml
@@ -9,9 +9,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../../parent-boot-1
+ ../../parent-boot-2
@@ -21,6 +21,10 @@
org.springframework.boot
spring-boot-starter-security
+
+ org.springframework.boot
+ spring-boot-starter-web
+
org.springframework.boot
spring-boot-starter-thymeleaf
diff --git a/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/SampleLDAPApplication.java b/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/SampleLDAPApplication.java
index ec585f2387..2d619cccfa 100644
--- a/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/SampleLDAPApplication.java
+++ b/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/SampleLDAPApplication.java
@@ -2,7 +2,7 @@ package com.baeldung;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@@ -19,15 +19,4 @@ public class SampleLDAPApplication extends SpringBootServletInitializer {
SpringApplication.run(SampleLDAPApplication.class, args);
}
- @Bean
- public WebMvcConfigurerAdapter adapter() {
- return new WebMvcConfigurerAdapter() {
- @Override
- public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController("/login")
- .setViewName("login");
- }
- };
- }
-
}
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/security/SecurityConfig.java b/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/config/SecurityConfig.java
similarity index 53%
rename from spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/security/SecurityConfig.java
rename to spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/config/SecurityConfig.java
index a00cb02459..69f90d9de9 100644
--- a/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/security/SecurityConfig.java
+++ b/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/config/SecurityConfig.java
@@ -1,4 +1,4 @@
-package com.baeldung.security;
+package com.baeldung.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
@@ -14,13 +14,26 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
- auth.ldapAuthentication().userSearchBase("ou=people").userSearchFilter("(uid={0})").groupSearchBase("ou=groups").groupSearchFilter("(member={0})").contextSource().root("dc=baeldung,dc=com").ldif("classpath:users.ldif");
+ auth.ldapAuthentication()
+ .userSearchBase("ou=people")
+ .userSearchFilter("(uid={0})")
+ .groupSearchBase("ou=groups")
+ .groupSearchFilter("(member={0})")
+ .contextSource()
+ .root("dc=baeldung,dc=com")
+ .ldif("classpath:users.ldif");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
- http.authorizeRequests().antMatchers("/", "/home").permitAll().anyRequest().authenticated();
- http.formLogin().loginPage("/login").permitAll().and().logout().logoutSuccessUrl("/");
+ http
+ .authorizeRequests()
+ .antMatchers("/", "/home", "/css/**")
+ .permitAll()
+ .anyRequest()
+ .authenticated()
+ .and().formLogin().loginPage("/login").permitAll()
+ .and().logout().logoutSuccessUrl("/");
}
}
diff --git a/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/config/WebConfig.java b/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/config/WebConfig.java
new file mode 100644
index 0000000000..9809be1844
--- /dev/null
+++ b/spring-security-modules/spring-security-ldap/src/main/java/com/baeldung/config/WebConfig.java
@@ -0,0 +1,16 @@
+package com.baeldung.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+ @Override
+ public void addViewControllers(ViewControllerRegistry registry) {
+ registry.addViewController("/login")
+ .setViewName("login");
+ }
+}
diff --git a/spring-security-modules/spring-security-ldap/src/main/resources/application.properties b/spring-security-modules/spring-security-ldap/src/main/resources/application.properties
new file mode 100644
index 0000000000..3d0221bb7b
--- /dev/null
+++ b/spring-security-modules/spring-security-ldap/src/main/resources/application.properties
@@ -0,0 +1 @@
+management.health.ldap.enabled=false
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-ldap/src/main/resources/webSecurityConfig.xml b/spring-security-modules/spring-security-ldap/src/main/resources/webSecurityConfig.xml
index c13f65de5e..adfd603e54 100644
--- a/spring-security-modules/spring-security-ldap/src/main/resources/webSecurityConfig.xml
+++ b/spring-security-modules/spring-security-ldap/src/main/resources/webSecurityConfig.xml
@@ -10,6 +10,7 @@
+
From 0628c8dd423c2c46932b474b5f2d0d51e6b26369 Mon Sep 17 00:00:00 2001
From: Ali Dehghani
Date: Mon, 30 Mar 2020 17:55:33 +0430
Subject: [PATCH 038/276] Introducing nullsFirst and nullsLast
---
.../com/baeldung/java8/Java8SortUnitTest.java | 63 ++++++++++++++++---
1 file changed, 53 insertions(+), 10 deletions(-)
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/Java8SortUnitTest.java b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/Java8SortUnitTest.java
index 57d9d8347b..9e510575fc 100644
--- a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/Java8SortUnitTest.java
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/Java8SortUnitTest.java
@@ -1,18 +1,17 @@
package com.baeldung.java8;
-import static org.hamcrest.Matchers.equalTo;
+import com.baeldung.java8.entity.Human;
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Ints;
+import org.junit.Assert;
+import org.junit.Test;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.baeldung.java8.entity.Human;
-import com.google.common.collect.Lists;
-import com.google.common.primitives.Ints;
+import static org.hamcrest.Matchers.equalTo;
public class Java8SortUnitTest {
@@ -113,11 +112,11 @@ public class Java8SortUnitTest {
humans.sort(Comparator.comparing(Human::getName));
Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
}
-
+
@Test
public final void givenStreamNaturalOrdering_whenSortingEntitiesByName_thenCorrectlySorted() {
final List letters = Lists.newArrayList("B", "A", "C");
-
+
final List sortedLetters = letters.stream().sorted().collect(Collectors.toList());
Assert.assertThat(sortedLetters.get(0), equalTo("A"));
}
@@ -126,7 +125,7 @@ public class Java8SortUnitTest {
public final void givenStreamCustomOrdering_whenSortingEntitiesByName_thenCorrectlySorted() {
final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
final Comparator nameComparator = (h1, h2) -> h1.getName().compareTo(h2.getName());
-
+
final List sortedHumans = humans.stream().sorted(nameComparator).collect(Collectors.toList());
Assert.assertThat(sortedHumans.get(0), equalTo(new Human("Jack", 12)));
}
@@ -164,4 +163,48 @@ public class Java8SortUnitTest {
Assert.assertThat(reverseSortedHumans.get(0), equalTo(new Human("Sarah", 10)));
}
+ @Test(expected = NullPointerException.class)
+ public final void givenANullElement_whenSortingEntitiesByName_thenThrowsNPE() {
+ final List humans = Lists.newArrayList(null, new Human("Jack", 12));
+
+ humans.sort((h1, h2) -> h1.getName().compareTo(h2.getName()));
+ }
+
+ @Test
+ public final void givenANullElement_whenSortingEntitiesByNameManually_thenMovesTheNullToLast() {
+ final List humans = Lists.newArrayList(null, new Human("Jack", 12), null);
+
+ humans.sort((h1, h2) -> {
+ if (h1 == null) return h2 == null ? 0 : 1;
+ else if (h2 == null) return -1;
+
+ return h1.getName().compareTo(h2.getName());
+ });
+
+ Assert.assertNotNull(humans.get(0));
+ Assert.assertNull(humans.get(1));
+ Assert.assertNull(humans.get(2));
+ }
+
+ @Test
+ public final void givenANullElement_whenSortingEntitiesByName_thenMovesTheNullToLast() {
+ final List humans = Lists.newArrayList(null, new Human("Jack", 12), null);
+
+ humans.sort(Comparator.nullsLast(Comparator.comparing(Human::getName)));
+
+ Assert.assertNotNull(humans.get(0));
+ Assert.assertNull(humans.get(1));
+ Assert.assertNull(humans.get(2));
+ }
+
+ @Test
+ public final void givenANullElement_whenSortingEntitiesByName_thenMovesTheNullToStart() {
+ final List humans = Lists.newArrayList(null, new Human("Jack", 12), null);
+
+ humans.sort(Comparator.nullsFirst(Comparator.comparing(Human::getName)));
+
+ Assert.assertNull(humans.get(0));
+ Assert.assertNull(humans.get(1));
+ Assert.assertNotNull(humans.get(2));
+ }
}
From 3f83ed67d3511a057bbf5b0db8e56f214ffd88a7 Mon Sep 17 00:00:00 2001
From: Krzysiek
Date: Mon, 30 Mar 2020 23:27:11 +0200
Subject: [PATCH 039/276] JAVA-42: Upgrade spring-security-kerberos to Spring
Boot 2
---
spring-security-modules/spring-security-kerberos/pom.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/spring-security-modules/spring-security-kerberos/pom.xml b/spring-security-modules/spring-security-kerberos/pom.xml
index 6846bdf063..51a48a78c6 100644
--- a/spring-security-modules/spring-security-kerberos/pom.xml
+++ b/spring-security-modules/spring-security-kerberos/pom.xml
@@ -10,9 +10,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../../parent-boot-1
+ ../../parent-boot-2
From 3f2d436db4e93cf57428c75758376b8e2d17b3c2 Mon Sep 17 00:00:00 2001
From: Krzysiek
Date: Mon, 30 Mar 2020 23:45:37 +0200
Subject: [PATCH 040/276] JAVA-42: Upgrade spring-security-cache-control to
Spring Boot 2
---
.../spring-security-cache-control/pom.xml | 38 +++----------------
.../ResourceEndpointIntegrationTest.java | 2 +-
2 files changed, 7 insertions(+), 33 deletions(-)
diff --git a/spring-security-modules/spring-security-cache-control/pom.xml b/spring-security-modules/spring-security-cache-control/pom.xml
index acc37b41ef..743b3c291d 100644
--- a/spring-security-modules/spring-security-cache-control/pom.xml
+++ b/spring-security-modules/spring-security-cache-control/pom.xml
@@ -8,9 +8,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../../parent-boot-1
+ ../../parent-boot-2
@@ -23,41 +23,15 @@
spring-boot-starter-web
- org.springframework.security
- spring-security-core
-
-
- org.springframework.security
- spring-security-config
-
-
- org.springframework.security
- spring-security-web
-
-
- javax.servlet
- javax.servlet-api
- ${javax.servlet-api.version}
+ org.springframework.boot
+ spring-boot-starter-security
- org.hamcrest
- hamcrest
- ${hamcrest.version}
+ org.springframework.boot
+ spring-boot-starter-test
test
-
-
- org.mockito
- mockito-core
- test
-
-
-
- org.springframework
- spring-test
-
-
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointIntegrationTest.java b/spring-security-modules/spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointIntegrationTest.java
index d6a1a97773..d4d24a4986 100644
--- a/spring-security-modules/spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointIntegrationTest.java
+++ b/spring-security-modules/spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointIntegrationTest.java
@@ -4,8 +4,8 @@ import static io.restassured.RestAssured.given;
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.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;
import io.restassured.http.ContentType;
From 405831d3da839c12ca73562112653842ee83ef44 Mon Sep 17 00:00:00 2001
From: patkorek
Date: Tue, 31 Mar 2020 07:36:44 +0200
Subject: [PATCH 041/276] changed tabs to spaces
---
...GraphQL collection.postman_collection.json | 334 +++++++++---------
1 file changed, 167 insertions(+), 167 deletions(-)
diff --git a/spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json b/spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json
index 7fcaa2c76d..f19bc1febb 100644
--- a/spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json
+++ b/spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json
@@ -1,169 +1,169 @@
{
- "info": {
- "_postman_id": "910d9690-f629-4491-bbbd-adb30982a386",
- "name": "GraphQL collection",
- "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
- },
- "item": [
- {
- "name": "mutations",
- "item": [
- {
- "name": "writePost",
- "request": {
- "method": "POST",
- "header": [],
- "body": {
- "mode": "graphql",
- "graphql": {
- "query": "mutation writePost ($title: String!, $text: String!, $category: String) {\n writePost (title: $title, text: $text, category: $category) {\n id\n title\n text\n category\n }\n}",
- "variables": "{\n \"title\": \"\",\n \"text\": \"\",\n \"category\": \"\"\n}"
- },
- "options": {
- "graphql": {}
- }
- },
- "url": {
- "raw": "http://localhost:9090/springbootapp/graphql",
- "protocol": "http",
- "host": [
- "localhost"
- ],
- "port": "9090",
- "path": [
- "springbootapp",
- "graphql"
- ]
- }
- },
- "response": []
- }
- ],
- "protocolProfileBehavior": {}
- },
- {
- "name": "queries",
- "item": [
- {
- "name": "get recent posts",
- "request": {
- "method": "POST",
- "header": [],
- "body": {
- "mode": "graphql",
- "graphql": {
- "query": "{\r\n recentPosts(count: 10, offset: 0) {\r\n id\r\n title\r\n category\r\n text\r\n author {\r\n id\r\n name\r\n thumbnail\r\n }\r\n }\r\n}",
- "variables": ""
- }
- },
- "url": {
- "raw": "http://localhost:9090/springbootapp/graphql",
- "protocol": "http",
- "host": [
- "localhost"
- ],
- "port": "9090",
- "path": [
- "springbootapp",
- "graphql"
- ]
- }
- },
- "response": []
- },
- {
- "name": "recentPosts - variables",
- "request": {
- "method": "POST",
- "header": [],
- "body": {
- "mode": "graphql",
- "graphql": {
- "query": "query recentPosts ($count: Int, $offset: Int) {\n recentPosts (count: $count, offset: $offset) {\n id\n title\n text\n category\n }\n}",
- "variables": "{\n \"count\": 1,\n \"offset\": 0\n}"
- },
- "options": {
- "graphql": {}
- }
- },
- "url": {
- "raw": "http://localhost:9090/springbootapp/graphql",
- "protocol": "http",
- "host": [
- "localhost"
- ],
- "port": "9090",
- "path": [
- "springbootapp",
- "graphql"
- ]
- }
- },
- "response": []
- },
- {
- "name": "get recent posts - raw",
- "request": {
- "method": "POST",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/graphql",
- "type": "text"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "query {\r\n recentPosts(count: 10, offset: 0) {\r\n id\r\n title\r\n category\r\n author {\r\n id\r\n name\r\n thumbnail\r\n }\r\n }\r\n}"
- },
- "url": {
- "raw": "http://localhost:9090/springbootapp/graphql",
- "protocol": "http",
- "host": [
- "localhost"
- ],
- "port": "9090",
- "path": [
- "springbootapp",
- "graphql"
- ]
- }
- },
- "response": []
- }
- ],
- "protocolProfileBehavior": {}
- }
- ],
- "event": [
- {
- "listen": "prerequest",
- "script": {
- "id": "b54f267b-c450-4f2d-8105-2f23bab4c922",
- "type": "text/javascript",
- "exec": [
- ""
- ]
- }
- },
- {
- "listen": "test",
- "script": {
- "id": "00b575be-03d4-4b29-b137-733ead139638",
- "type": "text/javascript",
- "exec": [
- ""
- ]
- }
- }
- ],
- "variable": [
- {
- "id": "20a274e5-6d51-40d6-81cb-af9eb115b21b",
- "key": "url",
- "value": "",
- "type": "string"
- }
- ],
- "protocolProfileBehavior": {}
+ "info": {
+ "_postman_id": "910d9690-f629-4491-bbbd-adb30982a386",
+ "name": "GraphQL collection",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+ },
+ "item": [
+ {
+ "name": "mutations",
+ "item": [
+ {
+ "name": "writePost",
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "mutation writePost ($title: String!, $text: String!, $category: String) {\n writePost (title: $title, text: $text, category: $category) {\n id\n title\n text\n category\n }\n}",
+ "variables": "{\n \"title\": \"\",\n \"text\": \"\",\n \"category\": \"\"\n}"
+ },
+ "options": {
+ "graphql": {}
+ }
+ },
+ "url": {
+ "raw": "http://localhost:9090/springbootapp/graphql",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "9090",
+ "path": [
+ "springbootapp",
+ "graphql"
+ ]
+ }
+ },
+ "response": []
+ }
+ ],
+ "protocolProfileBehavior": {}
+ },
+ {
+ "name": "queries",
+ "item": [
+ {
+ "name": "get recent posts",
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\r\n recentPosts(count: 10, offset: 0) {\r\n id\r\n title\r\n category\r\n text\r\n author {\r\n id\r\n name\r\n thumbnail\r\n }\r\n }\r\n}",
+ "variables": ""
+ }
+ },
+ "url": {
+ "raw": "http://localhost:9090/springbootapp/graphql",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "9090",
+ "path": [
+ "springbootapp",
+ "graphql"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "recentPosts - variables",
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "query recentPosts ($count: Int, $offset: Int) {\n recentPosts (count: $count, offset: $offset) {\n id\n title\n text\n category\n }\n}",
+ "variables": "{\n \"count\": 1,\n \"offset\": 0\n}"
+ },
+ "options": {
+ "graphql": {}
+ }
+ },
+ "url": {
+ "raw": "http://localhost:9090/springbootapp/graphql",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "9090",
+ "path": [
+ "springbootapp",
+ "graphql"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "get recent posts - raw",
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/graphql",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "query {\r\n recentPosts(count: 10, offset: 0) {\r\n id\r\n title\r\n category\r\n author {\r\n id\r\n name\r\n thumbnail\r\n }\r\n }\r\n}"
+ },
+ "url": {
+ "raw": "http://localhost:9090/springbootapp/graphql",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "9090",
+ "path": [
+ "springbootapp",
+ "graphql"
+ ]
+ }
+ },
+ "response": []
+ }
+ ],
+ "protocolProfileBehavior": {}
+ }
+ ],
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "id": "b54f267b-c450-4f2d-8105-2f23bab4c922",
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "id": "00b575be-03d4-4b29-b137-733ead139638",
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ }
+ ],
+ "variable": [
+ {
+ "id": "20a274e5-6d51-40d6-81cb-af9eb115b21b",
+ "key": "url",
+ "value": "",
+ "type": "string"
+ }
+ ],
+ "protocolProfileBehavior": {}
}
\ No newline at end of file
From a0478a7832e003ac3748ae5b574504b12e64dc1a Mon Sep 17 00:00:00 2001
From: ramkumarvenkat
Date: Tue, 31 Mar 2020 12:09:13 +0530
Subject: [PATCH 042/276] Fix code after article changes
---
.../com/baeldung/guava/entity/Profile.java | 20 ++++++++
.../com/baeldung/guava/entity/Session.java | 13 ++++++
.../java/com/baeldung/guava/entity/User.java | 20 ++++++++
.../guava/mapmaker/GuavaMapMakerUnitTest.java | 46 +++++++++++++------
4 files changed, 84 insertions(+), 15 deletions(-)
create mode 100644 guava-collections-map/src/main/java/com/baeldung/guava/entity/Profile.java
create mode 100644 guava-collections-map/src/main/java/com/baeldung/guava/entity/Session.java
create mode 100644 guava-collections-map/src/main/java/com/baeldung/guava/entity/User.java
diff --git a/guava-collections-map/src/main/java/com/baeldung/guava/entity/Profile.java b/guava-collections-map/src/main/java/com/baeldung/guava/entity/Profile.java
new file mode 100644
index 0000000000..17a6502f39
--- /dev/null
+++ b/guava-collections-map/src/main/java/com/baeldung/guava/entity/Profile.java
@@ -0,0 +1,20 @@
+package com.baeldung.guava.entity;
+
+public class Profile {
+ private long id;
+ private String type;
+
+ public Profile(long id, String type) {
+ this.id = id;
+ this.type = type;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return type;
+ }
+
+}
diff --git a/guava-collections-map/src/main/java/com/baeldung/guava/entity/Session.java b/guava-collections-map/src/main/java/com/baeldung/guava/entity/Session.java
new file mode 100644
index 0000000000..b834c23df1
--- /dev/null
+++ b/guava-collections-map/src/main/java/com/baeldung/guava/entity/Session.java
@@ -0,0 +1,13 @@
+package com.baeldung.guava.entity;
+
+public class Session {
+ private long id;
+
+ public Session(long id) {
+ this.id = id;
+ }
+
+ public long getId() {
+ return id;
+ }
+}
diff --git a/guava-collections-map/src/main/java/com/baeldung/guava/entity/User.java b/guava-collections-map/src/main/java/com/baeldung/guava/entity/User.java
new file mode 100644
index 0000000000..613045ec23
--- /dev/null
+++ b/guava-collections-map/src/main/java/com/baeldung/guava/entity/User.java
@@ -0,0 +1,20 @@
+package com.baeldung.guava.entity;
+
+public class User {
+ private long id;
+ private String name;
+
+ public User(long id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+}
diff --git a/guava-collections-map/src/test/java/com/baeldung/guava/mapmaker/GuavaMapMakerUnitTest.java b/guava-collections-map/src/test/java/com/baeldung/guava/mapmaker/GuavaMapMakerUnitTest.java
index 8da459f22e..e2bc1349c6 100644
--- a/guava-collections-map/src/test/java/com/baeldung/guava/mapmaker/GuavaMapMakerUnitTest.java
+++ b/guava-collections-map/src/test/java/com/baeldung/guava/mapmaker/GuavaMapMakerUnitTest.java
@@ -1,40 +1,56 @@
package com.baeldung.guava.mapmaker;
+import com.baeldung.guava.entity.Profile;
+import com.baeldung.guava.entity.Session;
+import com.baeldung.guava.entity.User;
import com.google.common.collect.MapMaker;
+import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.ConcurrentMap;
+import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertNotNull;
public class GuavaMapMakerUnitTest {
@Test
- public void whenMakeMap_thenCreated() {
- ConcurrentMap concurrentMap = new MapMaker().makeMap();
- assertNotNull(concurrentMap);
+ public void whenCreateCaches_thenCreated() {
+ ConcurrentMap sessionCache = new MapMaker().makeMap();
+ assertNotNull(sessionCache);
+
+ ConcurrentMap profileCache = new MapMaker().makeMap();
+ assertNotNull(profileCache);
+
+ User userA = new User(1, "UserA");
+
+ sessionCache.put(userA, new Session(100));
+ Assert.assertThat(sessionCache.size(), equalTo(1));
+
+ profileCache.put(userA, new Profile(1000, "Personal"));
+ Assert.assertThat(profileCache.size(), equalTo(1));
}
@Test
- public void whenMakeMapWithWeakKeys_thenCreated() {
- ConcurrentMap concurrentMap = new MapMaker().weakKeys().makeMap();
- assertNotNull(concurrentMap);
+ public void whenCreateCacheWithInitialCapacity_thenCreated() {
+ ConcurrentMap profileCache = new MapMaker().initialCapacity(100).makeMap();
+ assertNotNull(profileCache);
}
@Test
- public void whenMakeMapWithWeakValues_thenCreated() {
- ConcurrentMap concurrentMap = new MapMaker().weakValues().makeMap();
- assertNotNull(concurrentMap);
+ public void whenCreateCacheWithConcurrencyLevel_thenCreated() {
+ ConcurrentMap sessionCache = new MapMaker().concurrencyLevel(10).makeMap();
+ assertNotNull(sessionCache);
}
@Test
- public void whenMakeMapWithInitialCapacity_thenCreated() {
- ConcurrentMap concurrentMap = new MapMaker().initialCapacity(10).makeMap();
- assertNotNull(concurrentMap);
+ public void whenCreateCacheWithWeakKeys_thenCreated() {
+ ConcurrentMap sessionCache = new MapMaker().weakKeys().makeMap();
+ assertNotNull(sessionCache);
}
@Test
- public void whenMakeMapWithConcurrencyLevel_thenCreated() {
- ConcurrentMap concurrentMap = new MapMaker().concurrencyLevel(10).makeMap();
- assertNotNull(concurrentMap);
+ public void whenCreateCacheWithWeakValues_thenCreated() {
+ ConcurrentMap profileCache = new MapMaker().weakValues().makeMap();
+ assertNotNull(profileCache);
}
}
From 6534bddb6c73cae5ba2614fbc509535ae46babae Mon Sep 17 00:00:00 2001
From: mthomas
Date: Tue, 31 Mar 2020 04:43:06 -0500
Subject: [PATCH 043/276] Move code to
core-java-modules/core-java-concurrency-advanced-3Add Add missing 'Unit' in
test name
---
.../com/baeldung/atomicstampedreference}/SafeAccount.java | 6 +++---
.../atomicstampedreference/ThreadSafeAccountUnitTest.java} | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
rename core-java-modules/{core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic => core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference}/SafeAccount.java (82%)
rename core-java-modules/{core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeAccountTest.java => core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadSafeAccountUnitTest.java} (70%)
diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeAccount.java b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/SafeAccount.java
similarity index 82%
rename from core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeAccount.java
rename to core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/SafeAccount.java
index febfd481c3..fe41429e22 100644
--- a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeAccount.java
+++ b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/SafeAccount.java
@@ -1,12 +1,12 @@
-package com.baeldung.concurrent.atomic;
+package com.baeldung.atomicstampedreference;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;
public class SafeAccount {
- AtomicInteger stamp = new AtomicInteger(0);
- AtomicStampedReference balance = new AtomicStampedReference<>(0, 0);
+ private AtomicInteger stamp = new AtomicInteger(0);
+ private AtomicStampedReference balance = new AtomicStampedReference<>(0, 0);
public int getBalance() {
return this.balance.get(new int[1]);
diff --git a/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeAccountTest.java b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadSafeAccountUnitTest.java
similarity index 70%
rename from core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeAccountTest.java
rename to core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadSafeAccountUnitTest.java
index b9a5fe7773..bd33d5b4ec 100644
--- a/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeAccountTest.java
+++ b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadSafeAccountUnitTest.java
@@ -1,12 +1,12 @@
-package com.baeldung.concurrent.atomic;
+package com.baeldung.atomicstampedreference;
import org.junit.Assert;
import org.junit.Test;
-public class ThreadSafeAccountTest {
+public class ThreadSafeAccountUnitTest {
@Test
- public void givenMultiThread_whenSafeAccountSetBalance() throws InterruptedException {
+ public void givenMultiThread_whenSafeAccount_thenSetBalance() throws InterruptedException {
SafeAccount account = new SafeAccount();
Thread t = new Thread(() -> {
while (!account.withdrawal(100))
From aaffd9614fc1675ab05f992eec62c90be5aef76f Mon Sep 17 00:00:00 2001
From: naXa!
Date: Mon, 25 Mar 2019 02:00:03 +0300
Subject: [PATCH 044/276] [BAEL-2749] add dbunit module to parent pom
---
pom.xml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/pom.xml b/pom.xml
index 04a2ce054c..734e2c8ab9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -601,6 +601,8 @@
+ dbunit
+
parent-boot-1
parent-boot-2
parent-spring-4
@@ -1288,6 +1290,8 @@
+ dbunit
+
parent-boot-1
parent-boot-2
parent-spring-4
From a65c5bf202c3326514e7d6c1408bd9e445c06fd9 Mon Sep 17 00:00:00 2001
From: Joao Esperancinha
Date: Sun, 29 Mar 2020 11:37:19 +0200
Subject: [PATCH 045/276] [BAEL-2749] Introduces Assertj and uses builder
pattern
---
dbunit/pom.xml | 36 ++++++++++++++++---
.../baeldung/dbunit/OldSchoolDbUnitTest.java | 8 +++--
.../dbunit/PrepAndExpectedDbUnitTest.java | 12 +++++--
3 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/dbunit/pom.xml b/dbunit/pom.xml
index b77b15f2d4..ab0befcf4c 100644
--- a/dbunit/pom.xml
+++ b/dbunit/pom.xml
@@ -3,6 +3,16 @@
4.0.0
dbunit
1.0
+
+ 1.4.200
+
+ 1.8
+ 1.8
+ 3.8.1
+
+ 3.14.0
+ 2.6.0
+
dbunit
@@ -22,14 +32,30 @@
com.h2database
h2
- 1.4.197
+ ${h2.version}
+ test
+
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
test
-
-
- 2.6.0
-
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ ${maven-compiler-plugin.source}
+ ${maven-compiler-plugin.target}
+
+
+
+
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
index a703863614..2a2f25971b 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
@@ -6,6 +6,7 @@ import org.dbunit.JdbcDatabaseTester;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.FlatXmlDataSet;
+import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;
import org.junit.After;
import org.junit.Before;
@@ -16,6 +17,7 @@ import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -74,7 +76,7 @@ public class OldSchoolDbUnitTest {
final Connection connection = tester.getConnection().getConnection();
final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml");
- ITable expectedTable = (new FlatXmlDataSet(is)).getTable("items");
+ ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items");
//expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"produced"});
// Act
@@ -94,7 +96,7 @@ public class OldSchoolDbUnitTest {
final Connection connection = tester.getConnection().getConnection();
final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml");
- ITable expectedTable = (new FlatXmlDataSet(is)).getTable("items");
+ ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items");
//expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"produced"});
// Act
@@ -105,7 +107,7 @@ public class OldSchoolDbUnitTest {
ITable actualTable = databaseDataSet.getTable("items");
//actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"});
- Assertion.assertEquals(expectedTable, actualTable);
+ assertThat(actualTable).isEqualTo(actualTable);
}
}
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
index c3882d5eab..c322cf0ae3 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
@@ -1,6 +1,10 @@
package com.baeldung.dbunit;
-import org.dbunit.*;
+import org.dbunit.DefaultPrepAndExpectedTestCase;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.JdbcDatabaseTester;
+import org.dbunit.PrepAndExpectedTestCaseSteps;
+import org.dbunit.VerifyTableDefinition;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;
@@ -12,6 +16,8 @@ import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
+import static org.assertj.core.api.Assertions.assertThat;
+
public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase {
private static final String JDBC_DRIVER = org.h2.Driver.class.getName();
private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'";
@@ -63,8 +69,8 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase {
final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps);
// or place assertions at the end
- assertTrue(rs.next());
- assertEquals("Xavier", rs.getString("last_name"));
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString("last_name")).isEqualTo("Xavier");
}
@Test
From 71ba591868ed0f200f16c17a3d116cf6c32a559b Mon Sep 17 00:00:00 2001
From: Joao Esperancinha
Date: Sun, 29 Mar 2020 18:16:45 +0200
Subject: [PATCH 046/276] [BAEL-2749] Select and Delete for OldSchool
---
dbunit/pom.xml | 1 +
.../baeldung/dbunit/OldSchoolDbUnitTest.java | 39 +++++++++++--------
.../items_exp_delete_no_produced.xml | 8 ++++
3 files changed, 32 insertions(+), 16 deletions(-)
create mode 100644 dbunit/src/test/resources/items_exp_delete_no_produced.xml
diff --git a/dbunit/pom.xml b/dbunit/pom.xml
index ab0befcf4c..7ca53cd3be 100644
--- a/dbunit/pom.xml
+++ b/dbunit/pom.xml
@@ -13,6 +13,7 @@
3.14.0
2.6.0
+
dbunit
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
index 2a2f25971b..e64b49263a 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
@@ -5,7 +5,7 @@ import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
-import org.dbunit.dataset.xml.FlatXmlDataSet;
+import org.dbunit.dataset.filter.DefaultColumnFilter;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;
import org.junit.After;
@@ -18,8 +18,7 @@ import java.sql.Connection;
import java.sql.ResultSet;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.dbunit.Assertion.assertEquals;
public class OldSchoolDbUnitTest {
private static final String JDBC_DRIVER = org.h2.Driver.class.getName();
@@ -44,7 +43,7 @@ public class OldSchoolDbUnitTest {
private static IDataSet initDataSet() throws Exception {
final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("data.xml");
- return new FlatXmlDataSet(is);
+ return new FlatXmlDataSetBuilder().build(is);
}
@Before
@@ -59,35 +58,43 @@ public class OldSchoolDbUnitTest {
@Test
public void testSelect() throws Exception {
- // Arrange
final Connection connection = tester.getConnection().getConnection();
- // Act
final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1");
- // Assert
- assertTrue(rs.next());
- assertEquals("Grey T-Shirt", rs.getString("title"));
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt");
}
@Test
public void testDelete() throws Exception {
- // Arrange
final Connection connection = tester.getConnection().getConnection();
final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml");
ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items");
- //expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"produced"});
- // Act
connection.createStatement().executeUpdate("delete from ITEMS where id = 2");
- // Assert
final IDataSet databaseDataSet = tester.getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("items");
- //actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"});
- Assertion.assertEquals(expectedTable, actualTable);
+ assertEquals(expectedTable, actualTable);
+ }
+
+ @Test
+ public void testDeleteWithExcludedColumns() throws Exception {
+ final Connection connection = tester.getConnection().getConnection();
+
+ final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete_no_produced.xml");
+ ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items");
+
+ connection.createStatement().executeUpdate("delete from ITEMS where id = 2");
+
+ final IDataSet databaseDataSet = tester.getConnection().createDataSet();
+ ITable actualTable = databaseDataSet.getTable("items");
+ actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"});
+
+ assertEquals(expectedTable, actualTable);
}
@Test
@@ -107,7 +114,7 @@ public class OldSchoolDbUnitTest {
ITable actualTable = databaseDataSet.getTable("items");
//actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"});
- assertThat(actualTable).isEqualTo(actualTable);
+ assertEquals(expectedTable, actualTable);
}
}
diff --git a/dbunit/src/test/resources/items_exp_delete_no_produced.xml b/dbunit/src/test/resources/items_exp_delete_no_produced.xml
new file mode 100644
index 0000000000..c9b182a1b2
--- /dev/null
+++ b/dbunit/src/test/resources/items_exp_delete_no_produced.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
From e4f4f7110b33f753a50b5f56443b8dff8ab014b5 Mon Sep 17 00:00:00 2001
From: Joao Esperancinha
Date: Sun, 29 Mar 2020 21:47:00 +0200
Subject: [PATCH 047/276] [BAEL-2749] Code refactoring
---
dbunit/src/main/resources/logback.xml | 2 +-
.../baeldung/dbunit/ConnectionSettings.java | 8 ++++
.../baeldung/dbunit/OldSchoolDbUnitTest.java | 32 ++++++++-----
.../dbunit/PrepAndExpectedDbUnitTest.java | 48 +++++++------------
.../com/baeldung/dbunit/SampleDbUnitTest.java | 23 ++++-----
dbunit/src/test/resources/data.xml | 12 ++---
.../src/test/resources/items_exp_delete.xml | 8 ++--
.../items_exp_delete_no_produced.xml | 8 ++--
.../src/test/resources/items_exp_rename.xml | 10 ++--
.../items_exp_rename_no_produced.xml | 9 ++++
dbunit/src/test/resources/schema.sql | 34 ++++++-------
dbunit/src/test/resources/users.xml | 6 +--
.../src/test/resources/users_exp_delete.xml | 4 +-
.../src/test/resources/users_exp_rename.xml | 6 +--
14 files changed, 108 insertions(+), 102 deletions(-)
create mode 100644 dbunit/src/test/java/com/baeldung/dbunit/ConnectionSettings.java
create mode 100644 dbunit/src/test/resources/items_exp_rename_no_produced.xml
diff --git a/dbunit/src/main/resources/logback.xml b/dbunit/src/main/resources/logback.xml
index 7d900d8ea8..26beb6d5b4 100644
--- a/dbunit/src/main/resources/logback.xml
+++ b/dbunit/src/main/resources/logback.xml
@@ -8,6 +8,6 @@
-
+
\ No newline at end of file
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/ConnectionSettings.java b/dbunit/src/test/java/com/baeldung/dbunit/ConnectionSettings.java
new file mode 100644
index 0000000000..e842022292
--- /dev/null
+++ b/dbunit/src/test/java/com/baeldung/dbunit/ConnectionSettings.java
@@ -0,0 +1,8 @@
+package com.baeldung.dbunit;
+
+public class ConnectionSettings {
+ public static final String JDBC_DRIVER = org.h2.Driver.class.getName();
+ public static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'";
+ public static final String USER = "sa";
+ public static final String PASSWORD = "";
+}
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
index e64b49263a..0b63184951 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
@@ -1,6 +1,5 @@
package com.baeldung.dbunit;
-import org.dbunit.Assertion;
import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.dataset.IDataSet;
@@ -17,14 +16,14 @@ import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
+import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER;
+import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL;
+import static com.baeldung.dbunit.ConnectionSettings.PASSWORD;
+import static com.baeldung.dbunit.ConnectionSettings.USER;
import static org.assertj.core.api.Assertions.assertThat;
import static org.dbunit.Assertion.assertEquals;
public class OldSchoolDbUnitTest {
- private static final String JDBC_DRIVER = org.h2.Driver.class.getName();
- private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'";
- private static final String USER = "sa";
- private static final String PASSWORD = "";
private static IDatabaseTester tester = null;
@@ -99,20 +98,31 @@ public class OldSchoolDbUnitTest {
@Test
public void testUpdate() throws Exception {
- // Arrange
final Connection connection = tester.getConnection().getConnection();
final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml");
- ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items");
- //expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"produced"});
+ final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items");
- // Act
connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1");
- // Assert
final IDataSet databaseDataSet = tester.getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("items");
- //actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"});
+
+ assertEquals(expectedTable, actualTable);
+ }
+
+ @Test
+ public void testUpdateWithExcludedColumns() throws Exception {
+ final Connection connection = tester.getConnection().getConnection();
+
+ final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename_no_produced.xml");
+ ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items");
+
+ connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1");
+
+ final IDataSet databaseDataSet = tester.getConnection().createDataSet();
+ ITable actualTable = databaseDataSet.getTable("items");
+ actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"});
assertEquals(expectedTable, actualTable);
}
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
index c322cf0ae3..bb70136de2 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
@@ -16,13 +16,13 @@ import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
+import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER;
+import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL;
+import static com.baeldung.dbunit.ConnectionSettings.PASSWORD;
+import static com.baeldung.dbunit.ConnectionSettings.USER;
import static org.assertj.core.api.Assertions.assertThat;
public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase {
- private static final String JDBC_DRIVER = org.h2.Driver.class.getName();
- private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'";
- private static final String USER = "sa";
- private static final String PASSWORD = "";
@Override
public void setUp() throws Exception {
@@ -49,60 +49,46 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase {
@Test
public void testSelect() throws Exception {
- // Arrange
final Connection connection = getConnection().getConnection();
final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})};
final String[] prepDataFiles = {"/users.xml"};
final String[] expectedDataFiles = {"/users.xml"};
- final PrepAndExpectedTestCaseSteps testSteps = () -> {
- // invoke the method being tested here; for the sake of simplicity we use JDBC API directly in this example
- final ResultSet rs = connection.createStatement().executeQuery("select * from USERS where id = 1");
+ final PrepAndExpectedTestCaseSteps testSteps =
+ () -> connection
+ .createStatement()
+ .executeQuery("select * from USERS where id = 1");
- // either place assertions here
- //assertTrue(rs.next());
- //assertEquals("Xavier", rs.getString("last_name"));
-
- return rs;
- };
-
- // Act
final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps);
- // or place assertions at the end
assertThat(rs.next()).isTrue();
assertThat(rs.getString("last_name")).isEqualTo("Xavier");
}
@Test
public void testUpdate() throws Exception {
- // Arrange
final Connection connection = getConnection().getConnection();
final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})}; // define tables to verify
- final String[] prepDataFiles = {"/users.xml"}; // define prep files
- final String[] expectedDataFiles = {"/users_exp_rename.xml"}; // define expected files
- final PrepAndExpectedTestCaseSteps testSteps = () -> {
- // invoke the method being tested here; for the sake of simplicity we use JDBC API directly in this example
- return connection.createStatement().executeUpdate("update USERS set first_name = 'new name' where id = 1");
- // after this method exits, dbUnit will:
- // * verify configured tables
- // * cleanup tables as configured
- };
+ final String[] prepDataFiles = {"/users.xml"};
+ final String[] expectedDataFiles = {"/users_exp_rename.xml"};
+ final PrepAndExpectedTestCaseSteps testSteps =
+ () -> connection
+ .createStatement()
+ .executeUpdate("update USERS set first_name = 'new name' where id = 1");
- // Act
super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps);
}
@Test
public void testDelete() throws Exception {
- // Arrange
final Connection connection = getConnection().getConnection();
final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})};
final String[] prepDataFiles = {"/users.xml"};
final String[] expectedDataFiles = {"/users_exp_delete.xml"};
final PrepAndExpectedTestCaseSteps testSteps =
- () -> connection.createStatement().executeUpdate("delete from USERS where id = 2");
+ () -> connection
+ .createStatement()
+ .executeUpdate("delete from USERS where id = 2");
- // Act
super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps);
}
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java
index cfe4fd4e11..f7970754e7 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java
@@ -13,11 +13,13 @@ import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
+import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER;
+import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL;
+import static com.baeldung.dbunit.ConnectionSettings.PASSWORD;
+import static com.baeldung.dbunit.ConnectionSettings.USER;
+import static org.assertj.core.api.Assertions.assertThat;
+
public class SampleDbUnitTest extends DBTestCase {
- private static final String JDBC_DRIVER = org.h2.Driver.class.getName();
- private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'";
- private static final String USER = "sa";
- private static final String PASSWORD = "";
public SampleDbUnitTest(String name) {
super(name);
@@ -46,29 +48,23 @@ public class SampleDbUnitTest extends DBTestCase {
@Test
public void testSelect() throws Exception {
- // Arrange
final Connection connection = getConnection().getConnection();
- // Act
final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1");
- // Assert
- assertTrue(rs.next());
- assertEquals("Grey T-Shirt", rs.getString("title"));
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt");
}
@Test
public void testDelete() throws Exception {
- // Arrange
final Connection connection = getConnection().getConnection();
final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml");
ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items");
- // Act
connection.createStatement().executeUpdate("delete from ITEMS where id = 2");
- // Assert
final IDataSet databaseDataSet = getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("items");
@@ -77,16 +73,13 @@ public class SampleDbUnitTest extends DBTestCase {
@Test
public void testUpdate() throws Exception {
- // Arrange
final Connection connection = getConnection().getConnection();
final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml");
ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items");
- // Act
connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1");
- // Assert
final IDataSet databaseDataSet = getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("items");
diff --git a/dbunit/src/test/resources/data.xml b/dbunit/src/test/resources/data.xml
index e4498513e0..ac413cfd23 100644
--- a/dbunit/src/test/resources/data.xml
+++ b/dbunit/src/test/resources/data.xml
@@ -1,11 +1,11 @@
-
+
-
-
-
-
-
+
+
+
+
+
diff --git a/dbunit/src/test/resources/items_exp_delete.xml b/dbunit/src/test/resources/items_exp_delete.xml
index 1aaeff59ca..09b78da493 100644
--- a/dbunit/src/test/resources/items_exp_delete.xml
+++ b/dbunit/src/test/resources/items_exp_delete.xml
@@ -1,8 +1,8 @@
-
-
-
-
+
+
+
+
diff --git a/dbunit/src/test/resources/items_exp_delete_no_produced.xml b/dbunit/src/test/resources/items_exp_delete_no_produced.xml
index c9b182a1b2..dd76e8c6ce 100644
--- a/dbunit/src/test/resources/items_exp_delete_no_produced.xml
+++ b/dbunit/src/test/resources/items_exp_delete_no_produced.xml
@@ -1,8 +1,8 @@
-
-
-
-
+
+
+
+
diff --git a/dbunit/src/test/resources/items_exp_rename.xml b/dbunit/src/test/resources/items_exp_rename.xml
index 237280e758..830d83499f 100644
--- a/dbunit/src/test/resources/items_exp_rename.xml
+++ b/dbunit/src/test/resources/items_exp_rename.xml
@@ -1,9 +1,9 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/dbunit/src/test/resources/items_exp_rename_no_produced.xml b/dbunit/src/test/resources/items_exp_rename_no_produced.xml
new file mode 100644
index 0000000000..991c4726a0
--- /dev/null
+++ b/dbunit/src/test/resources/items_exp_rename_no_produced.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/dbunit/src/test/resources/schema.sql b/dbunit/src/test/resources/schema.sql
index 9b5018985a..dc4738ca76 100644
--- a/dbunit/src/test/resources/schema.sql
+++ b/dbunit/src/test/resources/schema.sql
@@ -1,28 +1,28 @@
CREATE TABLE IF NOT EXISTS USERS
(
- `id` int AUTO_INCREMENT NOT NULL,
- `first_name` varchar(100) NOT NULL,
- `last_name` varchar(100) NOT NULL,
- PRIMARY KEY (`id`)
+ `id` int AUTO_INCREMENT NOT NULL,
+ `first_name` varchar(100) NOT NULL,
+ `last_name` varchar(100) NOT NULL,
+ PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS ITEMS
(
- `id` int AUTO_INCREMENT NOT NULL,
- `title` varchar(100) NOT NULL,
- `produced` date,
- `price` float,
- PRIMARY KEY (`id`)
+ `id` int AUTO_INCREMENT NOT NULL,
+ `title` varchar(100) NOT NULL,
+ `produced` date,
+ `price` float,
+ PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS PURCHASES
(
- `id` int NOT NULL AUTO_INCREMENT,
- `id_user` int NOT NULL,
- `id_item` int NOT NULL,
- `total_price` float NOT NULL,
- `quantity` int(11) NOT NULL,
- PRIMARY KEY (`id`),
- FOREIGN KEY (`id_user`) REFERENCES USERS (`id`) ON DELETE CASCADE,
- FOREIGN KEY (`id_item`) REFERENCES ITEMS (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+ `id` int NOT NULL AUTO_INCREMENT,
+ `id_user` int NOT NULL,
+ `id_item` int NOT NULL,
+ `total_price` float NOT NULL,
+ `quantity` int(11) NOT NULL,
+ PRIMARY KEY (`id`),
+ FOREIGN KEY (`id_user`) REFERENCES USERS (`id`) ON DELETE CASCADE,
+ FOREIGN KEY (`id_item`) REFERENCES ITEMS (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);
diff --git a/dbunit/src/test/resources/users.xml b/dbunit/src/test/resources/users.xml
index cebadf2e67..d8ff78024e 100644
--- a/dbunit/src/test/resources/users.xml
+++ b/dbunit/src/test/resources/users.xml
@@ -1,7 +1,7 @@
-
-
-
+
+
+
diff --git a/dbunit/src/test/resources/users_exp_delete.xml b/dbunit/src/test/resources/users_exp_delete.xml
index 8b72ceef89..c4ea6e64e5 100644
--- a/dbunit/src/test/resources/users_exp_delete.xml
+++ b/dbunit/src/test/resources/users_exp_delete.xml
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/dbunit/src/test/resources/users_exp_rename.xml b/dbunit/src/test/resources/users_exp_rename.xml
index 9bc1254967..c187e1ebe5 100644
--- a/dbunit/src/test/resources/users_exp_rename.xml
+++ b/dbunit/src/test/resources/users_exp_rename.xml
@@ -1,7 +1,7 @@
-
-
-
+
+
+
From d5d1cc7d580b1749b9f29df644ea34cbddeee8ac Mon Sep 17 00:00:00 2001
From: Joao Esperancinha
Date: Tue, 31 Mar 2020 12:02:24 +0200
Subject: [PATCH 048/276] [BAEL-2749] Adds DataSourceBaseDBTestCase
---
.../baeldung/dbunit/DataSourceDBUnitTest.java | 46 +++++++++++++++++++
...{SampleDbUnitTest.java => DbUnitTest.java} | 12 ++---
2 files changed, 52 insertions(+), 6 deletions(-)
create mode 100644 dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
rename dbunit/src/test/java/com/baeldung/dbunit/{SampleDbUnitTest.java => DbUnitTest.java} (85%)
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
new file mode 100644
index 0000000000..154d93e0af
--- /dev/null
+++ b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
@@ -0,0 +1,46 @@
+package com.baeldung.dbunit;
+
+import org.dbunit.DataSourceBasedDBTestCase;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
+import org.h2.jdbcx.JdbcDataSource;
+import org.junit.Test;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
+ @Override
+ protected DataSource getDataSource() {
+ JdbcDataSource dataSource = new JdbcDataSource();
+ dataSource.setURL(
+ "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'");
+ dataSource.setUser("sa");
+ dataSource.setPassword("sa");
+ return dataSource;
+ }
+
+ @Override
+ protected IDataSet getDataSet() throws Exception {
+ return new FlatXmlDataSetBuilder().build(getClass()
+ .getClassLoader()
+ .getResourceAsStream("data.xml"));
+ }
+
+ @Test
+ public void testSimpleDataSet() throws SQLException {
+ final Connection connection = getDataSource()
+ .getConnection();
+
+ final ResultSet rs = connection
+ .createStatement()
+ .executeQuery("select * from iTEMS where id = 1");
+
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt");
+ }
+}
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java
similarity index 85%
rename from dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java
rename to dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java
index f7970754e7..8d6a94279a 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java
@@ -19,9 +19,9 @@ import static com.baeldung.dbunit.ConnectionSettings.PASSWORD;
import static com.baeldung.dbunit.ConnectionSettings.USER;
import static org.assertj.core.api.Assertions.assertThat;
-public class SampleDbUnitTest extends DBTestCase {
+public class DbUnitTest extends DBTestCase {
- public SampleDbUnitTest(String name) {
+ public DbUnitTest(String name) {
super(name);
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, JDBC_DRIVER);
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL);
@@ -32,7 +32,7 @@ public class SampleDbUnitTest extends DBTestCase {
@Override
protected IDataSet getDataSet() throws Exception {
- final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("data.xml");
+ final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("data.xml");
return new FlatXmlDataSetBuilder().build(is);
}
@@ -53,14 +53,14 @@ public class SampleDbUnitTest extends DBTestCase {
final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1");
assertThat(rs.next()).isTrue();
- assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt");
+ assertThat(rs.getString( "title")).isEqualTo("Grey T-Shirt");
}
@Test
public void testDelete() throws Exception {
final Connection connection = getConnection().getConnection();
- final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml");
+ final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml");
ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items");
connection.createStatement().executeUpdate("delete from ITEMS where id = 2");
@@ -75,7 +75,7 @@ public class SampleDbUnitTest extends DBTestCase {
public void testUpdate() throws Exception {
final Connection connection = getConnection().getConnection();
- final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml");
+ final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml");
ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items");
connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1");
From ef19d83db5f48290978f5c4e9e3c738a53e6087c Mon Sep 17 00:00:00 2001
From: Joao Esperancinha
Date: Tue, 31 Mar 2020 12:38:39 +0200
Subject: [PATCH 049/276] [BAEL-2749] USERS table name changed to CLIENTS
---
.../baeldung/dbunit/DataSourceDBUnitTest.java | 18 +++++++++++++++---
.../java/com/baeldung/dbunit/DbUnitTest.java | 1 -
.../dbunit/PrepAndExpectedDbUnitTest.java | 12 ++++++------
dbunit/src/test/resources/data.xml | 2 +-
dbunit/src/test/resources/schema.sql | 4 ++--
dbunit/src/test/resources/users.xml | 6 +++---
dbunit/src/test/resources/users_exp_delete.xml | 4 ++--
dbunit/src/test/resources/users_exp_rename.xml | 6 +++---
8 files changed, 32 insertions(+), 21 deletions(-)
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
index 154d93e0af..c8045394c4 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
@@ -1,7 +1,9 @@
package com.baeldung.dbunit;
+import org.dbunit.Assertion;
import org.dbunit.DataSourceBasedDBTestCase;
import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.h2.jdbcx.JdbcDataSource;
import org.junit.Test;
@@ -11,16 +13,17 @@ import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
+import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL;
import static org.assertj.core.api.Assertions.assertThat;
public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
+
@Override
protected DataSource getDataSource() {
JdbcDataSource dataSource = new JdbcDataSource();
- dataSource.setURL(
- "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'");
+ dataSource.setURL(JDBC_URL);
dataSource.setUser("sa");
- dataSource.setPassword("sa");
+ dataSource.setPassword("");
return dataSource;
}
@@ -43,4 +46,13 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
assertThat(rs.next()).isTrue();
assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt");
}
+
+ @Test
+ public void testEmptySchema() throws Exception {
+ IDataSet expectedDataSet = getDataSet();
+ ITable expectedTable = expectedDataSet.getTable("CLIENTS");
+ IDataSet databaseDataSet = getConnection().createDataSet();
+ ITable actualTable = databaseDataSet.getTable("CLIENTS");
+ Assertion.assertEquals(expectedTable, actualTable);
+ }
}
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java
index 8d6a94279a..479ea3dd51 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java
@@ -27,7 +27,6 @@ public class DbUnitTest extends DBTestCase {
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL);
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, USER);
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, PASSWORD);
- // System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_SCHEMA, "");
}
@Override
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
index bb70136de2..2c7e5de508 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
@@ -50,13 +50,13 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase {
@Test
public void testSelect() throws Exception {
final Connection connection = getConnection().getConnection();
- final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})};
+ final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})};
final String[] prepDataFiles = {"/users.xml"};
final String[] expectedDataFiles = {"/users.xml"};
final PrepAndExpectedTestCaseSteps testSteps =
() -> connection
.createStatement()
- .executeQuery("select * from USERS where id = 1");
+ .executeQuery("select * from CLIENTS where id = 1");
final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps);
@@ -67,13 +67,13 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase {
@Test
public void testUpdate() throws Exception {
final Connection connection = getConnection().getConnection();
- final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})}; // define tables to verify
+ final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; // define tables to verify
final String[] prepDataFiles = {"/users.xml"};
final String[] expectedDataFiles = {"/users_exp_rename.xml"};
final PrepAndExpectedTestCaseSteps testSteps =
() -> connection
.createStatement()
- .executeUpdate("update USERS set first_name = 'new name' where id = 1");
+ .executeUpdate("update CLIENTS set first_name = 'new name' where id = 1");
super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps);
}
@@ -81,13 +81,13 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase {
@Test
public void testDelete() throws Exception {
final Connection connection = getConnection().getConnection();
- final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})};
+ final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})};
final String[] prepDataFiles = {"/users.xml"};
final String[] expectedDataFiles = {"/users_exp_delete.xml"};
final PrepAndExpectedTestCaseSteps testSteps =
() -> connection
.createStatement()
- .executeUpdate("delete from USERS where id = 2");
+ .executeUpdate("delete from CLIENTS where id = 2");
super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps);
}
diff --git a/dbunit/src/test/resources/data.xml b/dbunit/src/test/resources/data.xml
index ac413cfd23..4230073fc6 100644
--- a/dbunit/src/test/resources/data.xml
+++ b/dbunit/src/test/resources/data.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/dbunit/src/test/resources/schema.sql b/dbunit/src/test/resources/schema.sql
index dc4738ca76..c2a8d2d630 100644
--- a/dbunit/src/test/resources/schema.sql
+++ b/dbunit/src/test/resources/schema.sql
@@ -1,4 +1,4 @@
-CREATE TABLE IF NOT EXISTS USERS
+CREATE TABLE IF NOT EXISTS CLIENTS
(
`id` int AUTO_INCREMENT NOT NULL,
`first_name` varchar(100) NOT NULL,
@@ -23,6 +23,6 @@ CREATE TABLE IF NOT EXISTS PURCHASES
`total_price` float NOT NULL,
`quantity` int(11) NOT NULL,
PRIMARY KEY (`id`),
- FOREIGN KEY (`id_user`) REFERENCES USERS (`id`) ON DELETE CASCADE,
+ FOREIGN KEY (`id_user`) REFERENCES CLIENTS (`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_item`) REFERENCES ITEMS (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);
diff --git a/dbunit/src/test/resources/users.xml b/dbunit/src/test/resources/users.xml
index d8ff78024e..9c14435362 100644
--- a/dbunit/src/test/resources/users.xml
+++ b/dbunit/src/test/resources/users.xml
@@ -1,7 +1,7 @@
-
-
-
+
+
+
diff --git a/dbunit/src/test/resources/users_exp_delete.xml b/dbunit/src/test/resources/users_exp_delete.xml
index c4ea6e64e5..3780c00c4c 100644
--- a/dbunit/src/test/resources/users_exp_delete.xml
+++ b/dbunit/src/test/resources/users_exp_delete.xml
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/dbunit/src/test/resources/users_exp_rename.xml b/dbunit/src/test/resources/users_exp_rename.xml
index c187e1ebe5..a576cc9e80 100644
--- a/dbunit/src/test/resources/users_exp_rename.xml
+++ b/dbunit/src/test/resources/users_exp_rename.xml
@@ -1,7 +1,7 @@
-
-
-
+
+
+
From 07947ce4d62daae7bc147fe7b4ac106b070b4d0e Mon Sep 17 00:00:00 2001
From: Joao Esperancinha
Date: Tue, 31 Mar 2020 13:31:11 +0200
Subject: [PATCH 050/276] [BAEL-2749] Insertion test with ignore cols
---
.../baeldung/dbunit/DataSourceDBUnitTest.java | 18 ++++++++++++++++++
dbunit/src/test/resources/expected-user.xml | 5 +++++
2 files changed, 23 insertions(+)
create mode 100644 dbunit/src/test/resources/expected-user.xml
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
index c8045394c4..d30305ecf2 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
@@ -55,4 +55,22 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
ITable actualTable = databaseDataSet.getTable("CLIENTS");
Assertion.assertEquals(expectedTable, actualTable);
}
+
+
+ @Test
+ public void testAssertByQuery() throws Exception {
+ IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(getClass()
+ .getClassLoader()
+ .getResourceAsStream("expected-user.xml"));
+ ITable expectedTable = expectedDataSet.getTable("CLIENTS");
+ Connection conn = getDataSource().getConnection();
+ conn.createStatement()
+ .executeUpdate(
+ "INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')");
+ ITable actualData = getConnection()
+ .createQueryTable(
+ "result_name",
+ "SELECT * FROM CLIENTS WHERE id='2'");
+ Assertion.assertEqualsIgnoreCols(expectedTable, actualData, new String[]{"id"});
+ }
}
diff --git a/dbunit/src/test/resources/expected-user.xml b/dbunit/src/test/resources/expected-user.xml
new file mode 100644
index 0000000000..379db13601
--- /dev/null
+++ b/dbunit/src/test/resources/expected-user.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
From 906d72859f67d1d9d9016d6b689805286d4c2675 Mon Sep 17 00:00:00 2001
From: Joao Esperancinha
Date: Tue, 31 Mar 2020 17:51:04 +0200
Subject: [PATCH 051/276] [BAEL-2749] Test Code Completion
---
.../baeldung/dbunit/DataSourceDBUnitTest.java | 49 ++++++++++++++++++-
.../java/com/baeldung/dbunit/DbUnitTest.java | 2 +-
.../baeldung/dbunit/OldSchoolDbUnitTest.java | 19 ++++++-
dbunit/src/test/resources/data.xml | 2 -
.../expected-ignoring-registered_at.xml | 9 ++++
.../resources/expected-multiple-failures.xml | 9 ++++
dbunit/src/test/resources/expected-user.xml | 3 +-
dbunit/src/test/resources/items.xml | 1 -
.../src/test/resources/items_exp_delete.xml | 1 -
.../items_exp_delete_no_produced.xml | 1 -
.../src/test/resources/items_exp_rename.xml | 1 -
.../items_exp_rename_no_produced.xml | 1 -
dbunit/src/test/resources/users.xml | 1 -
.../src/test/resources/users_exp_delete.xml | 1 -
.../src/test/resources/users_exp_rename.xml | 1 -
15 files changed, 85 insertions(+), 16 deletions(-)
create mode 100644 dbunit/src/test/resources/expected-ignoring-registered_at.xml
create mode 100644 dbunit/src/test/resources/expected-multiple-failures.xml
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
index d30305ecf2..7482f38535 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
@@ -2,10 +2,15 @@ package com.baeldung.dbunit;
import org.dbunit.Assertion;
import org.dbunit.DataSourceBasedDBTestCase;
+import org.dbunit.assertion.DiffCollectingFailureHandler;
+import org.dbunit.assertion.Difference;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
+import org.dbunit.operation.DatabaseOperation;
import org.h2.jdbcx.JdbcDataSource;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import javax.sql.DataSource;
@@ -14,6 +19,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL;
+import static java.util.stream.Collectors.joining;
import static org.assertj.core.api.Assertions.assertThat;
public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
@@ -34,6 +40,27 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
.getResourceAsStream("data.xml"));
}
+ @Override
+ protected DatabaseOperation getSetUpOperation() {
+ return DatabaseOperation.REFRESH;
+ }
+
+ @Override
+ protected DatabaseOperation getTearDownOperation() {
+ return DatabaseOperation.DELETE_ALL;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+
@Test
public void testSimpleDataSet() throws SQLException {
final Connection connection = getDataSource()
@@ -56,7 +83,6 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
Assertion.assertEquals(expectedTable, actualTable);
}
-
@Test
public void testAssertByQuery() throws Exception {
IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(getClass()
@@ -70,7 +96,26 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
ITable actualData = getConnection()
.createQueryTable(
"result_name",
- "SELECT * FROM CLIENTS WHERE id='2'");
+ "SELECT * FROM CLIENTS WHERE last_name='Jansen'");
Assertion.assertEqualsIgnoreCols(expectedTable, actualData, new String[]{"id"});
}
+
+ @Test(expected = AssertionError.class)
+ public void testMultipleFailures() throws Exception {
+ IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(getClass().getClassLoader().getResourceAsStream("expected-multiple-failures.xml"));
+ ITable expectedTable = expectedDataSet.getTable("ITEMS");
+ Connection conn = getDataSource().getConnection();
+ conn.createStatement().executeUpdate("INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')");
+ ITable actualData = getConnection().createDataSet().getTable("ITEMS");
+ DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler();
+ Assertion.assertEquals(expectedTable, actualData, collectingHandler);
+ if (!collectingHandler.getDiffList().isEmpty()) {
+ String message = (String) collectingHandler.getDiffList().stream().map(d -> formatDifference((Difference) d)).collect(joining("\n"));
+// throw new AssertionError(message);
+ }
+ }
+
+ private static String formatDifference(Difference diff) {
+ return "expected value in " + diff.getExpectedTable().getTableMetaData().getTableName() + "." + diff.getColumnName() + " row " + diff.getRowIndex() + ":" + diff.getExpectedValue() + ", but was: " + diff.getActualValue();
+ }
}
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java
index 479ea3dd51..1dee5afb28 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java
@@ -42,7 +42,7 @@ public class DbUnitTest extends DBTestCase {
@Override
protected DatabaseOperation getTearDownOperation() {
- return DatabaseOperation.NONE;
+ return DatabaseOperation.DELETE_ALL;
}
@Test
diff --git a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
index 0b63184951..3b46feb304 100644
--- a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
+++ b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
@@ -1,5 +1,6 @@
package com.baeldung.dbunit;
+import org.dbunit.Assertion;
import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.dataset.IDataSet;
@@ -36,7 +37,7 @@ public class OldSchoolDbUnitTest {
final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD);
tester.setDataSet(initDataSet());
tester.setSetUpOperation(DatabaseOperation.REFRESH);
- tester.setTearDownOperation(DatabaseOperation.NONE);
+ tester.setTearDownOperation(DatabaseOperation.DELETE_ALL);
return tester;
}
@@ -65,6 +66,22 @@ public class OldSchoolDbUnitTest {
assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt");
}
+ @Test
+ public void testIgnoringProduced() throws Exception {
+ final Connection connection = tester.getConnection().getConnection();
+ final String[] excludedColumns = {"id", "produced"};
+ final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(getClass().getClassLoader()
+ .getResourceAsStream("expected-ignoring-registered_at.xml"));
+ final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable("ITEMS"), excludedColumns);
+
+ connection.createStatement().executeUpdate("INSERT INTO ITEMS (title, price, produced) VALUES('Necklace', 199.99, now())");
+
+ final IDataSet databaseDataSet = tester.getConnection().createDataSet();
+ final ITable actualTable = DefaultColumnFilter.excludedColumnsTable(databaseDataSet.getTable("ITEMS"), excludedColumns);
+
+ Assertion.assertEquals(expectedTable, actualTable);
+ }
+
@Test
public void testDelete() throws Exception {
final Connection connection = tester.getConnection().getConnection();
diff --git a/dbunit/src/test/resources/data.xml b/dbunit/src/test/resources/data.xml
index 4230073fc6..290cc36890 100644
--- a/dbunit/src/test/resources/data.xml
+++ b/dbunit/src/test/resources/data.xml
@@ -1,8 +1,6 @@
-
-
diff --git a/dbunit/src/test/resources/expected-ignoring-registered_at.xml b/dbunit/src/test/resources/expected-ignoring-registered_at.xml
new file mode 100644
index 0000000000..ea57b6a961
--- /dev/null
+++ b/dbunit/src/test/resources/expected-ignoring-registered_at.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dbunit/src/test/resources/expected-multiple-failures.xml b/dbunit/src/test/resources/expected-multiple-failures.xml
new file mode 100644
index 0000000000..ea57b6a961
--- /dev/null
+++ b/dbunit/src/test/resources/expected-multiple-failures.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dbunit/src/test/resources/expected-user.xml b/dbunit/src/test/resources/expected-user.xml
index 379db13601..631dd84210 100644
--- a/dbunit/src/test/resources/expected-user.xml
+++ b/dbunit/src/test/resources/expected-user.xml
@@ -1,5 +1,4 @@
-
-
+
\ No newline at end of file
diff --git a/dbunit/src/test/resources/items.xml b/dbunit/src/test/resources/items.xml
index 04a975d7ee..d13e93bbe0 100644
--- a/dbunit/src/test/resources/items.xml
+++ b/dbunit/src/test/resources/items.xml
@@ -1,5 +1,4 @@
-
diff --git a/dbunit/src/test/resources/items_exp_delete.xml b/dbunit/src/test/resources/items_exp_delete.xml
index 09b78da493..a6fa2b33e8 100644
--- a/dbunit/src/test/resources/items_exp_delete.xml
+++ b/dbunit/src/test/resources/items_exp_delete.xml
@@ -1,5 +1,4 @@
-
diff --git a/dbunit/src/test/resources/items_exp_delete_no_produced.xml b/dbunit/src/test/resources/items_exp_delete_no_produced.xml
index dd76e8c6ce..3e7f854f5f 100644
--- a/dbunit/src/test/resources/items_exp_delete_no_produced.xml
+++ b/dbunit/src/test/resources/items_exp_delete_no_produced.xml
@@ -1,5 +1,4 @@
-
diff --git a/dbunit/src/test/resources/items_exp_rename.xml b/dbunit/src/test/resources/items_exp_rename.xml
index 830d83499f..32f1d57cf6 100644
--- a/dbunit/src/test/resources/items_exp_rename.xml
+++ b/dbunit/src/test/resources/items_exp_rename.xml
@@ -1,5 +1,4 @@
-
diff --git a/dbunit/src/test/resources/items_exp_rename_no_produced.xml b/dbunit/src/test/resources/items_exp_rename_no_produced.xml
index 991c4726a0..b42d3804fa 100644
--- a/dbunit/src/test/resources/items_exp_rename_no_produced.xml
+++ b/dbunit/src/test/resources/items_exp_rename_no_produced.xml
@@ -1,5 +1,4 @@
-
diff --git a/dbunit/src/test/resources/users.xml b/dbunit/src/test/resources/users.xml
index 9c14435362..9ac3909bc5 100644
--- a/dbunit/src/test/resources/users.xml
+++ b/dbunit/src/test/resources/users.xml
@@ -1,5 +1,4 @@
-
diff --git a/dbunit/src/test/resources/users_exp_delete.xml b/dbunit/src/test/resources/users_exp_delete.xml
index 3780c00c4c..2fe97ae6f6 100644
--- a/dbunit/src/test/resources/users_exp_delete.xml
+++ b/dbunit/src/test/resources/users_exp_delete.xml
@@ -1,5 +1,4 @@
-
diff --git a/dbunit/src/test/resources/users_exp_rename.xml b/dbunit/src/test/resources/users_exp_rename.xml
index a576cc9e80..95682118bb 100644
--- a/dbunit/src/test/resources/users_exp_rename.xml
+++ b/dbunit/src/test/resources/users_exp_rename.xml
@@ -1,5 +1,4 @@
-
From 0b1c5e01a5108350a493a06e07d2779a0b9e3f60 Mon Sep 17 00:00:00 2001
From: Joao Esperancinha
Date: Tue, 31 Mar 2020 20:18:11 +0200
Subject: [PATCH 052/276] [BAEL-2749] Improves code and makes a copy in
libraries-testing
---
dbunit/README.md | 2 -
dbunit/docs/db_schema.png | Bin 17099 -> 0 bytes
.../baeldung/dbunit/DataSourceDBUnitTest.java | 75 ++++----
.../java/com/baeldung/dbunit/DbUnitTest.java | 33 ++--
.../baeldung/dbunit/OldSchoolDbUnitTest.java | 85 +++++----
.../dbunit/PrepAndExpectedDbUnitTest.java | 23 +--
libraries-testing/pom.xml | 37 ++++
.../baeldung/dbunit/ConnectionSettings.java | 8 +
.../baeldung/dbunit/DataSourceDBUnitTest.java | 136 +++++++++++++++
.../java/com/baeldung/dbunit/DbUnitTest.java | 90 ++++++++++
.../baeldung/dbunit/OldSchoolDbUnitTest.java | 161 ++++++++++++++++++
.../dbunit/PrepAndExpectedDbUnitTest.java | 89 ++++++++++
.../src/test/resources/dbunit/data.xml | 9 +
.../expected-ignoring-registered_at.xml | 9 +
.../dbunit/expected-multiple-failures.xml | 9 +
.../test/resources/dbunit/expected-user.xml | 4 +
.../src/test/resources/dbunit/items.xml | 8 +
.../resources/dbunit/items_exp_delete.xml | 7 +
.../dbunit/items_exp_delete_no_produced.xml | 7 +
.../resources/dbunit/items_exp_rename.xml | 8 +
.../dbunit/items_exp_rename_no_produced.xml | 8 +
.../src/test/resources/dbunit/schema.sql | 28 +++
.../src/test/resources/dbunit/users.xml | 6 +
.../resources/dbunit/users_exp_delete.xml | 5 +
.../resources/dbunit/users_exp_rename.xml | 6 +
25 files changed, 758 insertions(+), 95 deletions(-)
delete mode 100644 dbunit/docs/db_schema.png
create mode 100644 libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java
create mode 100644 libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java
create mode 100644 libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java
create mode 100644 libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java
create mode 100644 libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java
create mode 100644 libraries-testing/src/test/resources/dbunit/data.xml
create mode 100644 libraries-testing/src/test/resources/dbunit/expected-ignoring-registered_at.xml
create mode 100644 libraries-testing/src/test/resources/dbunit/expected-multiple-failures.xml
create mode 100644 libraries-testing/src/test/resources/dbunit/expected-user.xml
create mode 100644 libraries-testing/src/test/resources/dbunit/items.xml
create mode 100644 libraries-testing/src/test/resources/dbunit/items_exp_delete.xml
create mode 100644 libraries-testing/src/test/resources/dbunit/items_exp_delete_no_produced.xml
create mode 100644 libraries-testing/src/test/resources/dbunit/items_exp_rename.xml
create mode 100644 libraries-testing/src/test/resources/dbunit/items_exp_rename_no_produced.xml
create mode 100644 libraries-testing/src/test/resources/dbunit/schema.sql
create mode 100644 libraries-testing/src/test/resources/dbunit/users.xml
create mode 100644 libraries-testing/src/test/resources/dbunit/users_exp_delete.xml
create mode 100644 libraries-testing/src/test/resources/dbunit/users_exp_rename.xml
diff --git a/dbunit/README.md b/dbunit/README.md
index 383bd6fb7e..333cac9439 100644
--- a/dbunit/README.md
+++ b/dbunit/README.md
@@ -1,6 +1,4 @@
### Database schema
-
-
### Relevant Articles:
- [Introduction To DBUnit](https://www.baeldung.com/dbunit)
diff --git a/dbunit/docs/db_schema.png b/dbunit/docs/db_schema.png
deleted file mode 100644
index d9185bacd2c624c8e05aea87bf542cfdfd7f1604..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 17099
zcmch91VJ!}GI}RUv>+r(2*N1QqxWuf5_R<6d+(z6
z-!1Yy&%5`2fBT$$UFV!XTv)U2wZ3buZ~dJpnIY$Y5iTVIUzPVav%%svsfVi2;60
z(eDB+822AMMnVz~my;BG<)XV4zoAOL7CX9s?c%i38RO6$T#=SwZAPC=hhk8vhx^8Q
z*#LRjxRBks5RbaoFYa^Wn-AE&AA=r-3LTBMOb=R@GsRgBsavVYrG>wGOr>)A<@u7s
z^fs|#&Wtt9po;d?v-)=(LkBv$2R%Cz>lKM!Z?Tb(M9(jn_pok+y9+`_62*OwKtk$8
zo&_Tz9UxT#?LtWZr<(&I!)U8__hyKYxIU@CNRd7xgOCsIRBmSfPkxJaK+5s27#r~*
zG6v{|b|Wo_IW3hMBw6xVuqc&L6v7t0DSG9~u4~{8J^CJ)nh02y2NI}y{pRx+^Gg$FS!w(9&E1EFBz$I6)Zflx43pyBK@pRkNHk|*mL@sdv$r;pt=FadpwQ?=zHNdLYUp`
zF=E$=R4ZeDuOJz%!k(2ue$8WNeoEsp^^NH#@Xo(m(OzoI=t5#
zzXlZrt-6`k>}PDay%Fq$Rk^rGDj)f3K@vy3E-Dw&-~b*&gh!uFTJcZhM}TWc%fgs1HHhc(^S$SoaX%_2&&^E=uy9?xVmmd3L1=gH@|d3U@_L+}J9#zeZdmZmu-5Pbw4##7NQ+(l99IQMFD~j3~
zbQ^50WpOG3nZE_(Y=$Hm&sz7~mjU`Kjq51&gG^89YIt!*&
zd#WI1JErze&qk;QrQdye`bWJ35d(&*au%Wk
z>GREqQy__f+kVP0D=Mr)x7kKs63{&`nqOAtAk=@y6kYLS6UuX-|2dD+_DCTp)kbk!
zMu%93iQ*MAHv>%bql2bqFd`-Bje>Pc>Tdyr2pL{7ok#oU#wAzC6C4uvtM?uoUD_tD
z8Il$6iIs&L+Q$gJ0Yyw+TznB_0F(ic`Q{Of2`GA%yW{d{^;Tj?t#3p`_2ebkcQHxJ
zT_Inr9}12`CjHd(3I(Qf_%d2F>n*8mq;hoNY;n#b41%YA9tyL8f6xA<7mAdG;+GX|
z08>2E_~5-fd;LV_+Jx9rDmq(0T~~N)%ABq2lanb+jo{gC^ZNGlT0eZ&Ds!A}P
z&Z!7d-FXe~awcmkQp;}64$Cxl?*^!7_RHu%(mAkUpCtP)vz0}zRS=PmeGAhJla^!Y
zbdm?`!7H(iL7$3>Z&7{EFOmYQYsHjg!btT9pP+}A58-s5x01!rOF;mIu_gV&M3|oP
z4zv%-hpCP95y!Qgv*qNISW89c?Bv#rPhvWM)!zc^z;g?&%=Oa?XzLK@Ogqb~ov*bM
z3NNKzcKbiLzNjTDv1N!Kc{Z20%|cif-mI_1co}$QUZhS=c
zbdFS;ch3BKv~_sr2=ol5$Vs&-#au{%{V438AtYIS=~UMhJcfBwXi`UOD@(~OD|Uts0`5LR5F
z@WI`q+3^4-Dv%@4YLZbk@vep@8L_xbaFiaFR9~->;+6fkB*3~x8o4x!udD-b~nU(LH{#@0~J3n-cgI|GUA1He^offg31
z)MK1Tcfbd9^-t4vqIl;;qz4LWJtB!qy6h~Lia--kA2Z{yGHdpS6xltr(NfWf%x~#?
zz3zH`t3eNZ@CD_qg~j;Eq$RGrnJy+2{O*5PK|+zV2P|O7VNBdvfr{X=jSau5bF{MN
z!6~7z%d6H7d8K2-JUp0bEf!m`==eMhvTW{w7rVs>@71*5SB4$6*goZZ?K^X&5iRP1
zBPvQy0tng+Dp^?!D;=Bbu-T!)KjJWf@v>+->6)1OeDA3Uw;h|4PThJA-<;IzJW$A<
zfPPPXG!Dg!q5K^UN}wyjE|6rusxaB!X7JeVx(5=@z}tpVDXUF=$Z|6R1_&
z9zt58+uSl_-=svJLwzU%fqfInJ4Q$fet0hnB1|`6(&2el+aRLopRT-tB{GGnBmFWY
z5Uq8tEwb{MZ42D5zI62Qnb2dWh{kzG0jrVEUwuy>mB6ka?OT2{Flq04QcNb}lc~vY
z)kRMD1g{c{R_!)s%(gg8Lru>F2^^L_Jvtzn1~2du3Pp(Z=Ku13Jad$jw=l5VH*si!
zhUpzfJD_GqT2fq6ZsI;nrG<5B(mEk8%Qf)Uf{D*TX4jpxI&xGqeE)uU@nG8iDcCX*
z4^QsH?|>q?1-^h_gF(KP?C2euBKXnH8bMVt0VrZiJW8m`XZ=T$UYj_3J6ZV=*qvuJs0Gm~W*xe~S=_I~)B`5j7q|nasUe$W}_1JvL!uet1bvSkAW~|#l
zg7x0(CVE=9ceQ=k_MO_j9oXDQ&YSJ!B8&kx(LsmUq>zJT{z|kmuT^U@+b-=R4Dl)T?gZIpq{-GsHt7r}(WGoljovf_K51o8tX4=|s^|4`7@46$FBH)}pl!-^t#OJCm-#^nTeZa-5Vg{^Cn8;_h@&^8KDt)A!a*ZZB+S
zL1LUr?C*96rD|h59Jp4UN5=C@lz8U%V;Y~Dk@p7u<$eaX!8Oi|eXTXJY9#p$n;%Le
zgD($W?Y``PvDjtVGv?<(>{vEI^{#i>AXGj!u*xKi9+EpAtjQn3666im4jh-hXxxjU
zkk+1T({|1qQXuctBxWvAv!3|wrGMe%8WObW*G|VC@&4
z?8!RND4HxeKGOaJ^O~$Psrm3
z3%5pc`J|CWzAf{fgn-YTD%hxl53*!nwK1`>$iYRgDYNl=?XXVw<=1Ou|Ln`*0@(1!
zy!2+oyu!eyX)2?<5y7_d^2CckaMVGPu%-+R@62N6rma#}Cz?3T^@aEwj-TbBwhIq2
z1cYexl(JSe#rlvx0+Zd};qUXV&P8m`b{pt0a3pRKW|;j4Rok6TgHSm==pEk!5j=Yqznef{1(Q0DHgUe6)f5sf%)paqr&)!1Fwc*4Ck#kKnoFyL
zLtVDOs^=$niu=#+Ip0&%W(C0l0&DdcYQ^_=AH}+ok>!-6gnZwq+gUZ_!;e|bEuyoC
z-qO6s`^({R-NVNUP@R$>2j5GHtJxF9&IrVDa |