org.apache.maven.plugins
maven-jar-plugin
diff --git a/core-java/README.md b/core-java/README.md
index e74f6cf815..ade7f46504 100644
--- a/core-java/README.md
+++ b/core-java/README.md
@@ -145,3 +145,9 @@
- [Common Java Exceptions](http://www.baeldung.com/java-common-exceptions)
- [Java Constructors vs Static Factory Methods](https://www.baeldung.com/java-constructors-vs-static-factory-methods)
- [Differences Between Final, Finally and Finalize in Java](https://www.baeldung.com/java-final-finally-finalize)
+- [Static and Dynamic Binding in Java](https://www.baeldung.com/java-static-dynamic-binding)
+- [Java List Initialization in One Line](https://www.baeldung.com/java-init-list-one-line)
+- [Difference Between Throw and Throws in Java](https://www.baeldung.com/java-throw-throws)
+- [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist)
+- [Throw Exception in Optional in Java 8](https://www.baeldung.com/java-optional-throw-exception)
+- [Add a Character to a String at a Given Position](https://www.baeldung.com/java-add-character-to-string)
diff --git a/core-java/src/main/java/com/baeldung/doubles/SplitFloatingPointNumbers.java b/core-java/src/main/java/com/baeldung/doubles/SplitFloatingPointNumbers.java
new file mode 100644
index 0000000000..a28ac3d5a1
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/doubles/SplitFloatingPointNumbers.java
@@ -0,0 +1,40 @@
+package com.baeldung.doubles;
+
+import java.math.BigDecimal;
+
+public class SplitFloatingPointNumbers {
+
+ public static void main(String[] args) {
+
+ double doubleNumber = 24.04;
+ splitUsingFloatingTypes(doubleNumber);
+ splitUsingString(doubleNumber);
+ splitUsingBigDecimal(doubleNumber);
+ }
+
+ private static void splitUsingFloatingTypes(double doubleNumber) {
+ System.out.println("Using Floating Point Arithmetics:");
+ int intPart = (int) doubleNumber;
+ System.out.println("Double Number: "+doubleNumber);
+ System.out.println("Integer Part: "+ intPart);
+ System.out.println("Decimal Part: "+ (doubleNumber - intPart));
+ }
+
+ private static void splitUsingString(double doubleNumber) {
+ System.out.println("Using String Operations:");
+ String doubleAsString = String.valueOf(doubleNumber);
+ int indexOfDecimal = doubleAsString.indexOf(".");
+ System.out.println("Double Number: "+doubleNumber);
+ System.out.println("Integer Part: "+ doubleAsString.substring(0, indexOfDecimal));
+ System.out.println("Decimal Part: "+ doubleAsString.substring(indexOfDecimal));
+ }
+
+ private static void splitUsingBigDecimal(double doubleNumber) {
+ System.out.println("Using BigDecimal Operations:");
+ BigDecimal bigDecimal = new BigDecimal(String.valueOf(doubleNumber));
+ int intValue = bigDecimal.intValue();
+ System.out.println("Double Number: "+bigDecimal.toPlainString());
+ System.out.println("Integer Part: "+intValue);
+ System.out.println("Decimal Part: "+bigDecimal.subtract(new BigDecimal(intValue)).toPlainString());
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/heapdump/HeapDump.java b/core-java/src/main/java/com/baeldung/heapdump/HeapDump.java
new file mode 100644
index 0000000000..8cce20de8d
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/heapdump/HeapDump.java
@@ -0,0 +1,25 @@
+package com.baeldung.heapdump;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+
+import javax.management.MBeanServer;
+
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.nio.file.Paths;
+
+public class HeapDump {
+
+ public static void dumpHeap(String filePath, boolean live) throws IOException {
+ MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+ HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy(
+ server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
+ mxBean.dumpHeap(filePath, live);
+ }
+
+ public static void main(String[] args) throws IOException {
+ String file = Paths.get("dump.hprof").toFile().getPath();
+
+ dumpHeap(file, true);
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java b/core-java/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
new file mode 100644
index 0000000000..e2259e4249
--- /dev/null
+++ b/core-java/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/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java b/core-java/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
new file mode 100644
index 0000000000..4f5337f963
--- /dev/null
+++ b/core-java/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/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java b/core-java/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
new file mode 100644
index 0000000000..36c9b65070
--- /dev/null
+++ b/core-java/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/src/main/java/com/baeldung/zoneddatetime/OffsetDateTimeExample.java b/core-java/src/main/java/com/baeldung/zoneddatetime/OffsetDateTimeExample.java
new file mode 100644
index 0000000000..fb92eb8d0d
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/zoneddatetime/OffsetDateTimeExample.java
@@ -0,0 +1,13 @@
+package com.baeldung.zoneddatetime;
+
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+
+public class OffsetDateTimeExample {
+
+ public OffsetDateTime getCurrentTimeByZoneOffset(String offset) {
+ ZoneOffset zoneOffSet= ZoneOffset.of(offset);
+ OffsetDateTime date = OffsetDateTime.now(zoneOffSet);
+ return date;
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/zoneddatetime/OffsetTimeExample.java b/core-java/src/main/java/com/baeldung/zoneddatetime/OffsetTimeExample.java
new file mode 100644
index 0000000000..58e2d4d5ad
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/zoneddatetime/OffsetTimeExample.java
@@ -0,0 +1,13 @@
+package com.baeldung.zoneddatetime;
+
+import java.time.OffsetTime;
+import java.time.ZoneOffset;
+
+public class OffsetTimeExample {
+
+ public OffsetTime getCurrentTimeByZoneOffset(String offset) {
+ ZoneOffset zoneOffSet = ZoneOffset.of(offset);
+ OffsetTime time = OffsetTime.now(zoneOffSet);
+ return time;
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/zoneddatetime/ZoneDateTimeExample.java b/core-java/src/main/java/com/baeldung/zoneddatetime/ZoneDateTimeExample.java
new file mode 100644
index 0000000000..b54b8c5225
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/zoneddatetime/ZoneDateTimeExample.java
@@ -0,0 +1,21 @@
+package com.baeldung.zoneddatetime;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+
+public class ZoneDateTimeExample {
+
+ public ZonedDateTime getCurrentTimeByZoneId(String region) {
+ ZoneId zone = ZoneId.of(region);
+ ZonedDateTime date = ZonedDateTime.now(zone);
+ return date;
+ }
+
+ public ZonedDateTime convertZonedDateTime(ZonedDateTime sourceDate, String destZone) {
+
+ ZoneId destZoneId = ZoneId.of(destZone);
+ ZonedDateTime destDate = sourceDate.withZoneSameInstant(destZoneId);
+
+ return destDate;
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java b/core-java/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
new file mode 100644
index 0000000000..8e90725c77
--- /dev/null
+++ b/core-java/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/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java b/core-java/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
new file mode 100644
index 0000000000..3acfb0ba9d
--- /dev/null
+++ b/core-java/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/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java b/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java
new file mode 100644
index 0000000000..8dbfcaf5e7
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java
@@ -0,0 +1,100 @@
+package com.baeldung.removingdecimals;
+
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This benchmark compares some of the approaches to formatting a floating-point
+ * value into a {@link String} while removing the decimal part.
+ *
+ * To run, simply run the {@link RemovingDecimalsManualTest#runBenchmarks()} test
+ * at the end of this class.
+ *
+ * The benchmark takes about 15 minutes to run. Since it is using {@link Mode#Throughput},
+ * higher numbers mean better performance.
+ */
+@BenchmarkMode(Mode.Throughput)
+@Warmup(iterations = 5)
+@Measurement(iterations = 20)
+@OutputTimeUnit(TimeUnit.MICROSECONDS)
+@State(Scope.Benchmark)
+public class RemovingDecimalsManualTest {
+ @Param(value = {"345.56", "345345345.56", "345345345345345345.56"}) double doubleValue;
+
+ NumberFormat nf;
+ DecimalFormat df;
+
+ @Setup
+ public void readyFormatters() {
+ nf = NumberFormat.getInstance();
+ nf.setMaximumFractionDigits(0);
+ df = new DecimalFormat("#,###");
+ }
+
+ @Benchmark
+ public String whenCastToInt_thenValueIsTruncated() {
+ return String.valueOf((int) doubleValue);
+ }
+
+ @Benchmark
+ public String whenUsingStringFormat_thenValueIsRounded() {
+ return String.format("%.0f", doubleValue);
+ }
+
+ @Benchmark
+ public String whenUsingNumberFormat_thenValueIsRounded() {
+ nf.setRoundingMode(RoundingMode.HALF_UP);
+ return nf.format(doubleValue);
+ }
+
+ @Benchmark
+ public String whenUsingNumberFormatWithFloor_thenValueIsTruncated() {
+ nf.setRoundingMode(RoundingMode.FLOOR);
+ return nf.format(doubleValue);
+ }
+
+ @Benchmark
+ public String whenUsingDecimalFormat_thenValueIsRounded() {
+ df.setRoundingMode(RoundingMode.HALF_UP);
+ return df.format(doubleValue);
+ }
+
+ @Benchmark
+ public String whenUsingDecimalFormatWithFloor_thenValueIsTruncated() {
+ df.setRoundingMode(RoundingMode.FLOOR);
+ return df.format(doubleValue);
+ }
+
+ @Benchmark
+ public String whenUsingBigDecimalDoubleValue_thenValueIsTruncated() {
+ BigDecimal big = new BigDecimal(doubleValue);
+ big = big.setScale(0, RoundingMode.FLOOR);
+ return big.toString();
+ }
+
+ @Benchmark
+ public String whenUsingBigDecimalDoubleValueWithHalfUp_thenValueIsRounded() {
+ BigDecimal big = new BigDecimal(doubleValue);
+ big = big.setScale(0, RoundingMode.HALF_UP);
+ return big.toString();
+ }
+
+ @Test
+ public void runBenchmarks() throws Exception {
+ Options options = new OptionsBuilder()
+ .include(this.getClass().getSimpleName()).threads(1)
+ .forks(1).shouldFailOnError(true).shouldDoGC(true)
+ .jvmArgs("-server").build();
+
+ new Runner(options).run();
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java b/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java
new file mode 100644
index 0000000000..2f634b553b
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java
@@ -0,0 +1,95 @@
+package com.baeldung.removingdecimals;
+
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+/**
+ * Tests that demonstrate some different approaches for formatting a
+ * floating-point value into a {@link String} while removing the decimal part.
+ */
+public class RemovingDecimalsUnitTest {
+ private final double doubleValue = 345.56;
+
+ @Test
+ public void whenCastToInt_thenValueIsTruncated() {
+ String truncated = String.valueOf((int) doubleValue);
+ assertEquals("345", truncated);
+ }
+
+ @Test
+ public void givenALargeDouble_whenCastToInt_thenValueIsNotTruncated() {
+ double outOfIntRange = 6_000_000_000.56;
+ String truncationAttempt = String.valueOf((int) outOfIntRange);
+ assertNotEquals("6000000000", truncationAttempt);
+ }
+
+ @Test
+ public void whenUsingStringFormat_thenValueIsRounded() {
+ String rounded = String.format("%.0f", doubleValue);
+ assertEquals("346", rounded);
+ }
+
+ @Test
+ public void givenALargeDouble_whenUsingStringFormat_thenValueIsStillRounded() {
+ double outOfIntRange = 6_000_000_000.56;
+ String rounded = String.format("%.0f", outOfIntRange);
+ assertEquals("6000000001", rounded);
+ }
+
+ @Test
+ public void whenUsingNumberFormat_thenValueIsRounded() {
+ NumberFormat nf = NumberFormat.getInstance();
+ nf.setMaximumFractionDigits(0);
+ nf.setRoundingMode(RoundingMode.HALF_UP);
+ String rounded = nf.format(doubleValue);
+ assertEquals("346", rounded);
+ }
+
+ @Test
+ public void whenUsingNumberFormatWithFloor_thenValueIsTruncated() {
+ NumberFormat nf = NumberFormat.getInstance();
+ nf.setMaximumFractionDigits(0);
+ nf.setRoundingMode(RoundingMode.FLOOR);
+ String truncated = nf.format(doubleValue);
+ assertEquals("345", truncated);
+ }
+
+ @Test
+ public void whenUsingDecimalFormat_thenValueIsRounded() {
+ DecimalFormat df = new DecimalFormat("#,###");
+ df.setRoundingMode(RoundingMode.HALF_UP);
+ String rounded = df.format(doubleValue);
+ assertEquals("346", rounded);
+ }
+
+ @Test
+ public void whenUsingDecimalFormatWithFloor_thenValueIsTruncated() {
+ DecimalFormat df = new DecimalFormat("#,###");
+ df.setRoundingMode(RoundingMode.FLOOR);
+ String truncated = df.format(doubleValue);
+ assertEquals("345", truncated);
+ }
+
+ @Test
+ public void whenUsingBigDecimalDoubleValue_thenValueIsTruncated() {
+ BigDecimal big = new BigDecimal(doubleValue);
+ big = big.setScale(0, RoundingMode.FLOOR);
+ String truncated = big.toString();
+ assertEquals("345", truncated);
+ }
+
+ @Test
+ public void whenUsingBigDecimalDoubleValueWithHalfUp_thenValueIsRounded() {
+ BigDecimal big = new BigDecimal(doubleValue);
+ big = big.setScale(0, RoundingMode.HALF_UP);
+ String truncated = big.toString();
+ assertEquals("346", truncated);
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/zoneddatetime/OffsetDateTimeExampleUnitTest.java b/core-java/src/test/java/com/baeldung/zoneddatetime/OffsetDateTimeExampleUnitTest.java
new file mode 100644
index 0000000000..a08d3737cd
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/zoneddatetime/OffsetDateTimeExampleUnitTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.zoneddatetime;
+
+import static org.junit.Assert.assertTrue;
+
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+
+import org.junit.Test;
+
+public class OffsetDateTimeExampleUnitTest {
+
+ OffsetDateTimeExample offsetDateTimeExample = new OffsetDateTimeExample();
+
+ @Test
+ public void givenZoneOffset_whenGetCurrentTime_thenResultHasZone() {
+ String offset = "+02:00";
+ OffsetDateTime time = offsetDateTimeExample.getCurrentTimeByZoneOffset(offset);
+
+ assertTrue(time.getOffset()
+ .equals(ZoneOffset.of(offset)));
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/zoneddatetime/OffsetTimeExampleUnitTest.java b/core-java/src/test/java/com/baeldung/zoneddatetime/OffsetTimeExampleUnitTest.java
new file mode 100644
index 0000000000..488f934179
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/zoneddatetime/OffsetTimeExampleUnitTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.zoneddatetime;
+
+import static org.junit.Assert.assertTrue;
+
+import java.time.OffsetTime;
+import java.time.ZoneOffset;
+
+import org.junit.Test;
+
+public class OffsetTimeExampleUnitTest {
+
+ OffsetTimeExample offsetTimeExample = new OffsetTimeExample();
+
+ @Test
+ public void givenZoneOffset_whenGetCurrentTime_thenResultHasZone() {
+ String offset = "+02:00";
+ OffsetTime time = offsetTimeExample.getCurrentTimeByZoneOffset(offset);
+
+ assertTrue(time.getOffset()
+ .equals(ZoneOffset.of(offset)));
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/zoneddatetime/ZoneDateTimeExampleUnitTest.java b/core-java/src/test/java/com/baeldung/zoneddatetime/ZoneDateTimeExampleUnitTest.java
new file mode 100644
index 0000000000..e78ff3e3fd
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/zoneddatetime/ZoneDateTimeExampleUnitTest.java
@@ -0,0 +1,33 @@
+package com.baeldung.zoneddatetime;
+
+import static org.junit.Assert.assertTrue;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+
+import org.junit.Test;
+
+public class ZoneDateTimeExampleUnitTest {
+
+ ZoneDateTimeExample zoneDateTimeExample = new ZoneDateTimeExample();
+
+ @Test
+ public void givenZone_whenGetCurrentTime_thenResultHasZone() {
+ String zone = "Europe/Berlin";
+ ZonedDateTime time = zoneDateTimeExample.getCurrentTimeByZoneId(zone);
+
+ assertTrue(time.getZone()
+ .equals(ZoneId.of(zone)));
+ }
+
+ @Test
+ public void givenZones_whenConvertDateByZone_thenGetConstantDiff() {
+ String sourceZone = "Europe/Berlin";
+ String destZone = "Asia/Tokyo";
+ ZonedDateTime sourceDate = zoneDateTimeExample.getCurrentTimeByZoneId(sourceZone);
+ ZonedDateTime destDate = zoneDateTimeExample.convertZonedDateTime(sourceDate, destZone);
+
+ assertTrue(sourceDate.toInstant()
+ .compareTo(destDate.toInstant()) == 0);
+ }
+}
diff --git a/core-kotlin/README.md b/core-kotlin/README.md
index 734b2c08b3..f63451bc02 100644
--- a/core-kotlin/README.md
+++ b/core-kotlin/README.md
@@ -8,7 +8,6 @@
- [Generics in Kotlin](http://www.baeldung.com/kotlin-generics)
- [Introduction to Kotlin Coroutines](http://www.baeldung.com/kotlin-coroutines)
- [Destructuring Declarations in Kotlin](http://www.baeldung.com/kotlin-destructuring-declarations)
-- [Kotlin with Mockito](http://www.baeldung.com/kotlin-mockito)
- [Lazy Initialization in Kotlin](http://www.baeldung.com/kotlin-lazy-initialization)
- [Overview of Kotlin Collections API](http://www.baeldung.com/kotlin-collections-api)
- [Converting a List to Map in Kotlin](http://www.baeldung.com/kotlin-list-to-map)
@@ -19,8 +18,6 @@
- [Extension Methods in Kotlin](http://www.baeldung.com/kotlin-extension-methods)
- [Infix Functions in Kotlin](http://www.baeldung.com/kotlin-infix-functions)
- [Try-with-resources in Kotlin](http://www.baeldung.com/kotlin-try-with-resources)
-- [HTTP Requests with Kotlin and khttp](http://www.baeldung.com/kotlin-khttp)
-- [Kotlin Dependency Injection with Kodein](http://www.baeldung.com/kotlin-kodein-dependency-injection)
- [Regular Expressions in Kotlin](http://www.baeldung.com/kotlin-regular-expressions)
- [Objects in Kotlin](http://www.baeldung.com/kotlin-objects)
- [Reading from a File in Kotlin](http://www.baeldung.com/kotlin-read-file)
@@ -28,13 +25,12 @@
- [Filtering Kotlin Collections](http://www.baeldung.com/kotlin-filter-collection)
- [Writing to a File in Kotlin](http://www.baeldung.com/kotlin-write-file)
- [Lambda Expressions in Kotlin](http://www.baeldung.com/kotlin-lambda-expressions)
-- [Writing Specifications with Kotlin and Spek](http://www.baeldung.com/kotlin-spek)
-- [Processing JSON with Kotlin and Klaxson](http://www.baeldung.com/kotlin-json-klaxson)
- [Kotlin String Templates](http://www.baeldung.com/kotlin-string-template)
-- [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security)
-- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor)
- [Working with Enums in Kotlin](http://www.baeldung.com/kotlin-enum)
- [Create a Java and Kotlin Project with Maven](http://www.baeldung.com/kotlin-maven-java-project)
- [Reflection with Kotlin](http://www.baeldung.com/kotlin-reflection)
- [Get a Random Number in Kotlin](http://www.baeldung.com/kotlin-random-number)
- [Idiomatic Logging in Kotlin](http://www.baeldung.com/kotlin-logging)
+- [Kotlin Constructors](https://www.baeldung.com/kotlin-constructors)
+- [Creational Design Patterns in Kotlin: Builder](https://www.baeldung.com/kotlin-builder-pattern)
+- [Kotlin Nested and Inner Classes](https://www.baeldung.com/kotlin-inner-classes)
\ No newline at end of file
diff --git a/core-kotlin/build.gradle b/core-kotlin/build.gradle
index 6c1e06aa25..2b6527fca7 100755
--- a/core-kotlin/build.gradle
+++ b/core-kotlin/build.gradle
@@ -6,7 +6,6 @@ version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.2.41'
- ext.ktor_version = '0.9.2'
repositories {
mavenCentral()
@@ -44,14 +43,6 @@ sourceSets {
}
dependencies {
- compile "io.ktor:ktor-server-netty:$ktor_version"
compile "ch.qos.logback:logback-classic:1.2.1"
- compile "io.ktor:ktor-gson:$ktor_version"
testCompile group: 'junit', name: 'junit', version: '4.12'
- implementation 'com.beust:klaxon:3.0.1'
-
-}
-task runServer(type: JavaExec) {
- main = 'APIServer'
- classpath = sourceSets.main.runtimeClasspath
}
\ No newline at end of file
diff --git a/core-kotlin/kotlin-ktor/webapp/WEB-INF/web.xml b/core-kotlin/kotlin-ktor/webapp/WEB-INF/web.xml
deleted file mode 100755
index 513a80cb27..0000000000
--- a/core-kotlin/kotlin-ktor/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
- io.ktor.ktor.config
- application.conf
-
-
-
- KtorServlet
- KtorServlet
- io.ktor.server.servlet.ServletApplicationEngine
-
-
- true
-
-
-
- 304857600
- 304857600
- 0
-
-
-
-
- KtorServlet
- /
-
-
-
\ No newline at end of file
diff --git a/core-kotlin/pom.xml b/core-kotlin/pom.xml
index 6fdc7c7c1a..0894a57320 100644
--- a/core-kotlin/pom.xml
+++ b/core-kotlin/pom.xml
@@ -12,33 +12,7 @@
../parent-kotlin
-
-
- exposed
- exposed
- https://dl.bintray.com/kotlin/exposed
-
-
-
-
- org.jetbrains.spek
- spek-api
- 1.1.5
- test
-
-
- org.jetbrains.spek
- spek-subject-extension
- 1.1.5
- test
-
-
- org.jetbrains.spek
- spek-junit-platform-engine
- 1.1.5
- test
-
org.apache.commons
commons-math3
@@ -50,56 +24,52 @@
${junit.platform.version}
test
-
- khttp
- khttp
- ${khttp.version}
-
-
- com.nhaarman
- mockito-kotlin
- ${mockito-kotlin.version}
- test
-
-
- com.github.salomonbrys.kodein
- kodein
- ${kodein.version}
-
org.assertj
assertj-core
${assertj.version}
test
-
- com.beust
- klaxon
- ${klaxon.version}
-
-
- org.jetbrains.exposed
- exposed
- ${exposed.version}
-
com.h2database
h2
${h2database.version}
+
+ com.github.kittinunf.fuel
+ fuel
+ ${fuel.version}
+
+
+ com.github.kittinunf.fuel
+ fuel-gson
+ ${fuel.version}
+
+
+ com.github.kittinunf.fuel
+ fuel-rxjava
+ ${fuel.version}
+
+
+ com.github.kittinunf.fuel
+ fuel-coroutines
+ ${fuel.version}
+
+
+ nl.komponents.kovenant
+ kovenant
+ 3.3.0
+ pom
+
- 1.5.0
- 4.1.0
- 3.0.4
- 0.1.0
3.6.1
1.1.1
5.2.0
3.10.0
1.4.197
- 0.10.4
+ 1.15.0
-
\ No newline at end of file
+
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/fuel/Interceptors.kt b/core-kotlin/src/main/kotlin/com/baeldung/fuel/Interceptors.kt
new file mode 100644
index 0000000000..377ef979dc
--- /dev/null
+++ b/core-kotlin/src/main/kotlin/com/baeldung/fuel/Interceptors.kt
@@ -0,0 +1,11 @@
+package com.baeldung.fuel
+
+import com.github.kittinunf.fuel.core.Request
+
+fun tokenInterceptor() = {
+ next: (Request) -> Request ->
+ { req: Request ->
+ req.header(mapOf("Authorization" to "Bearer AbCdEf123456"))
+ next(req)
+ }
+}
\ No newline at end of file
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/fuel/Post.kt b/core-kotlin/src/main/kotlin/com/baeldung/fuel/Post.kt
new file mode 100644
index 0000000000..035dfe7aa0
--- /dev/null
+++ b/core-kotlin/src/main/kotlin/com/baeldung/fuel/Post.kt
@@ -0,0 +1,15 @@
+package com.baeldung.fuel
+
+import com.github.kittinunf.fuel.core.ResponseDeserializable
+import com.google.gson.Gson
+
+data class Post(var userId:Int,
+ var id:Int,
+ var title:String,
+ var body:String){
+
+
+ class Deserializer : ResponseDeserializable> {
+ override fun deserialize(content: String): Array = Gson().fromJson(content, Array::class.java)
+ }
+}
\ No newline at end of file
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/fuel/PostRoutingAPI.kt b/core-kotlin/src/main/kotlin/com/baeldung/fuel/PostRoutingAPI.kt
new file mode 100644
index 0000000000..8238c41e56
--- /dev/null
+++ b/core-kotlin/src/main/kotlin/com/baeldung/fuel/PostRoutingAPI.kt
@@ -0,0 +1,42 @@
+package com.baeldung.fuel
+
+import com.github.kittinunf.fuel.core.Method
+import com.github.kittinunf.fuel.util.FuelRouting
+
+sealed class PostRoutingAPI : FuelRouting {
+
+ override val basePath = "https://jsonplaceholder.typicode.com"
+
+ class posts(val id: String, override val body: String?): PostRoutingAPI()
+
+ class comments(val postId: String, override val body: String?): PostRoutingAPI()
+
+ override val method: Method
+ get() {
+ return when(this) {
+ is PostRoutingAPI.posts -> Method.GET
+ is PostRoutingAPI.comments -> Method.GET
+ }
+ }
+
+ override val path: String
+ get() {
+ return when(this) {
+ is PostRoutingAPI.posts -> "/posts"
+ is PostRoutingAPI.comments -> "/comments"
+ }
+ }
+
+ override val params: List>?
+ get() {
+ return when(this) {
+ is PostRoutingAPI.posts -> listOf("id" to this.id)
+ is PostRoutingAPI.comments -> listOf("postId" to this.postId)
+ }
+ }
+
+ override val headers: Map?
+ get() {
+ return null
+ }
+}
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/ktor/APIServer.kt b/core-kotlin/src/main/kotlin/com/baeldung/ktor/APIServer.kt
deleted file mode 100755
index a12182ccc8..0000000000
--- a/core-kotlin/src/main/kotlin/com/baeldung/ktor/APIServer.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-@file:JvmName("APIServer")
-
-
-import io.ktor.application.call
-import io.ktor.application.install
-import io.ktor.features.CallLogging
-import io.ktor.features.ContentNegotiation
-import io.ktor.features.DefaultHeaders
-import io.ktor.gson.gson
-import io.ktor.request.path
-import io.ktor.request.receive
-import io.ktor.response.respond
-import io.ktor.routing.*
-import io.ktor.server.engine.embeddedServer
-import io.ktor.server.netty.Netty
-import org.slf4j.event.Level
-
-data class Author(val name: String, val website: String)
-data class ToDo(var id: Int, val name: String, val description: String, val completed: Boolean)
-
-fun main(args: Array) {
-
- val toDoList = ArrayList();
- val jsonResponse = """{
- "id": 1,
- "task": "Pay waterbill",
- "description": "Pay water bill today",
- }"""
-
-
- embeddedServer(Netty, 8080) {
- install(DefaultHeaders) {
- header("X-Developer", "Baeldung")
- }
- install(CallLogging) {
- level = Level.DEBUG
- filter { call -> call.request.path().startsWith("/todo") }
- filter { call -> call.request.path().startsWith("/author") }
- }
- install(ContentNegotiation) {
- gson {
- setPrettyPrinting()
- }
- }
- routing() {
- route("/todo") {
- post {
- var toDo = call.receive();
- toDo.id = toDoList.size;
- toDoList.add(toDo);
- call.respond("Added")
-
- }
- delete("/{id}") {
- call.respond(toDoList.removeAt(call.parameters["id"]!!.toInt()));
- }
- get("/{id}") {
-
- call.respond(toDoList[call.parameters["id"]!!.toInt()]);
- }
- get {
- call.respond(toDoList);
- }
- }
- get("/author"){
- call.respond(Author("Baeldung","baeldung.com"));
-
- }
-
-
- }
- }.start(wait = true)
-}
\ No newline at end of file
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt
index 17f5a43479..a6687b6e0a 100644
--- a/core-kotlin/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt
+++ b/core-kotlin/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt
@@ -93,6 +93,7 @@ internal class BuilderPatternUnitTest {
Assertions.assertNull(foodOrder.fish)
}
+
@Test
fun whenBuildingFoodOrderApplySettingValues_thenFieldsNotNull() {
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/fuel/FuelHttpUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/fuel/FuelHttpUnitTest.kt
new file mode 100644
index 0000000000..f0f9267618
--- /dev/null
+++ b/core-kotlin/src/test/kotlin/com/baeldung/fuel/FuelHttpUnitTest.kt
@@ -0,0 +1,286 @@
+package com.baeldung.fuel
+
+import awaitObjectResult
+import awaitStringResponse
+import com.github.kittinunf.fuel.Fuel
+import com.github.kittinunf.fuel.core.FuelManager
+import com.github.kittinunf.fuel.core.Request
+import com.github.kittinunf.fuel.core.interceptors.cUrlLoggingRequestInterceptor
+import com.github.kittinunf.fuel.gson.responseObject
+import com.github.kittinunf.fuel.httpGet
+import com.github.kittinunf.fuel.rx.rx_object
+import com.google.gson.Gson
+import kotlinx.coroutines.experimental.runBlocking
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Test
+import java.io.File
+import java.util.concurrent.CountDownLatch
+
+internal class FuelHttpUnitTest {
+
+ @Test
+ fun whenMakingAsyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val latch = CountDownLatch(1)
+
+ "http://httpbin.org/get".httpGet().response{
+ request, response, result ->
+
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+
+ latch.countDown()
+ }
+
+ latch.await()
+
+ }
+
+ @Test
+ fun whenMakingSyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val (request, response, result) = "http://httpbin.org/get".httpGet().response()
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+
+ }
+
+ @Test
+ fun whenMakingSyncHttpGetURLEncodedRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val (request, response, result) =
+ "https://jsonplaceholder.typicode.com/posts"
+ .httpGet(listOf("id" to "1")).response()
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+
+ }
+
+ @Test
+ fun whenMakingAsyncHttpPostRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val latch = CountDownLatch(1)
+
+ Fuel.post("http://httpbin.org/post").response{
+ request, response, result ->
+
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+
+ latch.countDown()
+ }
+
+ latch.await()
+
+ }
+
+ @Test
+ fun whenMakingSyncHttpPostRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val (request, response, result) = Fuel.post("http://httpbin.org/post").response()
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+ }
+
+ @Test
+ fun whenMakingSyncHttpPostRequestwithBody_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val (request, response, result) = Fuel.post("https://jsonplaceholder.typicode.com/posts")
+ .body("{ \"title\" : \"foo\",\"body\" : \"bar\",\"id\" : \"1\"}")
+ .response()
+
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(201,response.statusCode)
+ }
+
+ @Test
+ fun givenFuelInstance_whenMakingSyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ FuelManager.instance.basePath = "http://httpbin.org"
+ FuelManager.instance.baseHeaders = mapOf("OS" to "macOS High Sierra")
+
+ FuelManager.instance.addRequestInterceptor(cUrlLoggingRequestInterceptor())
+ FuelManager.instance.addRequestInterceptor(tokenInterceptor())
+
+
+ val (request, response, result) = "/get"
+ .httpGet().response()
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+ }
+
+ @Test
+ fun givenInterceptors_whenMakingSyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ FuelManager.instance.basePath = "http://httpbin.org"
+ FuelManager.instance.addRequestInterceptor(cUrlLoggingRequestInterceptor())
+ FuelManager.instance.addRequestInterceptor(tokenInterceptor())
+
+ val (request, response, result) = "/get"
+ .httpGet().response()
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+ }
+
+ @Test
+ fun whenDownloadFile_thenCreateFileResponseNotNullAndErrorNullAndStatusCode200() {
+
+ Fuel.download("http://httpbin.org/bytes/32768").destination { response, url ->
+ File.createTempFile("temp", ".tmp")
+ }.response{
+ request, response, result ->
+
+ val (data, error) = result
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+ }
+ }
+
+ @Test
+ fun whenDownloadFilewithProgressHandler_thenCreateFileResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val (request, response, result) = Fuel.download("http://httpbin.org/bytes/327680")
+ .destination { response, url -> File.createTempFile("temp", ".tmp")
+ }.progress { readBytes, totalBytes ->
+ val progress = readBytes.toFloat() / totalBytes.toFloat()
+ }.response ()
+
+ val (data, error) = result
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+
+
+ }
+
+ @Test
+ fun whenMakeGetRequest_thenDeserializePostwithGson() {
+
+ val latch = CountDownLatch(1)
+
+ "https://jsonplaceholder.typicode.com/posts/1".httpGet().responseObject { _,_, result ->
+ val post = result.component1()
+ Assertions.assertEquals(1, post?.userId)
+ latch.countDown()
+ }
+
+ latch.await()
+
+ }
+
+ @Test
+ fun whenMakePOSTRequest_thenSerializePostwithGson() {
+
+ val post = Post(1,1, "Lorem", "Lorem Ipse dolor sit amet")
+
+ val (request, response, result) = Fuel.post("https://jsonplaceholder.typicode.com/posts")
+ .header("Content-Type" to "application/json")
+ .body(Gson().toJson(post).toString())
+ .response()
+
+ Assertions.assertEquals(201,response.statusCode)
+
+ }
+
+ @Test
+ fun whenMakeGETRequestWithRxJava_thenDeserializePostwithGson() {
+
+ val latch = CountDownLatch(1)
+
+
+ "https://jsonplaceholder.typicode.com/posts?id=1"
+ .httpGet().rx_object(Post.Deserializer()).subscribe{
+ res, throwable ->
+
+ val post = res.component1()
+ Assertions.assertEquals(1, post?.get(0)?.userId)
+ latch.countDown()
+ }
+
+ latch.await()
+
+ }
+
+ @Test
+ fun whenMakeGETRequestUsingCoroutines_thenResponseStatusCode200() {
+
+ runBlocking {
+ val (request, response, result) = Fuel.get("http://httpbin.org/get").awaitStringResponse()
+
+ result.fold({ data ->
+ Assertions.assertEquals(200, response.statusCode)
+
+ }, { error -> })
+ }
+
+ }
+
+ @Test
+ fun whenMakeGETRequestUsingCoroutines_thenDeserializeResponse() {
+
+
+ runBlocking {
+ Fuel.get("https://jsonplaceholder.typicode.com/posts?id=1").awaitObjectResult(Post.Deserializer())
+ .fold({ data ->
+ Assertions.assertEquals(1, data.get(0).userId)
+ }, { error -> })
+ }
+
+ }
+
+ @Test
+ fun whenMakeGETPostRequestUsingRoutingAPI_thenDeserializeResponse() {
+
+ val latch = CountDownLatch(1)
+
+ Fuel.request(PostRoutingAPI.posts("1",null))
+ .responseObject(Post.Deserializer()) {
+ request, response, result ->
+ Assertions.assertEquals(1, result.component1()?.get(0)?.userId)
+ latch.countDown()
+ }
+
+ latch.await()
+ }
+
+ @Test
+ fun whenMakeGETCommentRequestUsingRoutingAPI_thenResponseStausCode200() {
+
+ val latch = CountDownLatch(1)
+
+ Fuel.request(PostRoutingAPI.comments("1",null))
+ .responseString { request, response, result ->
+ Assertions.assertEquals(200, response.statusCode)
+ latch.countDown()
+ }
+
+ latch.await()
+ }
+
+
+}
\ No newline at end of file
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/CoroutinesTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/CoroutinesUnitTest.kt
similarity index 100%
rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/CoroutinesTest.kt
rename to core-kotlin/src/test/kotlin/com/baeldung/kotlin/CoroutinesUnitTest.kt
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTest.kt
new file mode 100644
index 0000000000..469118f0f6
--- /dev/null
+++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTest.kt
@@ -0,0 +1,191 @@
+package com.baeldung.kotlin
+
+import nl.komponents.kovenant.*
+import nl.komponents.kovenant.Kovenant.deferred
+import nl.komponents.kovenant.combine.and
+import nl.komponents.kovenant.combine.combine
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import java.io.IOException
+import java.util.*
+import java.util.concurrent.TimeUnit
+
+class KovenantTest {
+ @Before
+ fun setupTestMode() {
+ Kovenant.testMode { error ->
+ println("An unexpected error occurred")
+ Assert.fail(error.message)
+ }
+ }
+
+ @Test
+ fun testSuccessfulDeferred() {
+ val def = deferred()
+ Assert.assertFalse(def.promise.isDone())
+
+ def.resolve(1L)
+ Assert.assertTrue(def.promise.isDone())
+ Assert.assertTrue(def.promise.isSuccess())
+ Assert.assertFalse(def.promise.isFailure())
+ }
+
+ @Test
+ fun testFailedDeferred() {
+ val def = deferred()
+ Assert.assertFalse(def.promise.isDone())
+
+ def.reject(RuntimeException())
+ Assert.assertTrue(def.promise.isDone())
+ Assert.assertFalse(def.promise.isSuccess())
+ Assert.assertTrue(def.promise.isFailure())
+ }
+
+ @Test
+ fun testResolveDeferredTwice() {
+ val def = deferred()
+ def.resolve(1L)
+ try {
+ def.resolve(1L)
+ } catch (e: AssertionError) {
+ // Expected.
+ // This is slightly unusual. The AssertionError comes from Assert.fail() from setupTestMode()
+ }
+ }
+
+ @Test
+ fun testSuccessfulTask() {
+ val promise = task { 1L }
+ Assert.assertTrue(promise.isDone())
+ Assert.assertTrue(promise.isSuccess())
+ Assert.assertFalse(promise.isFailure())
+ }
+
+ @Test
+ fun testFailedTask() {
+ val promise = task { throw RuntimeException() }
+ Assert.assertTrue(promise.isDone())
+ Assert.assertFalse(promise.isSuccess())
+ Assert.assertTrue(promise.isFailure())
+ }
+
+ @Test
+ fun testCallbacks() {
+ val promise = task { 1L }
+
+ promise.success {
+ println("This was a success")
+ Assert.assertEquals(1L, it)
+ }
+
+ promise.fail {
+ println(it)
+ Assert.fail("This shouldn't happen")
+ }
+
+ promise.always {
+ println("This always happens")
+ }
+ }
+
+ @Test
+ fun testGetValues() {
+ val promise = task { 1L }
+ Assert.assertEquals(1L, promise.get())
+ }
+
+ @Test
+ fun testAllSucceed() {
+ val numbers = all(
+ task { 1L },
+ task { 2L },
+ task { 3L }
+ )
+
+ Assert.assertEquals(listOf(1L, 2L, 3L), numbers.get())
+ }
+
+ @Test
+ fun testOneFails() {
+ val runtimeException = RuntimeException()
+
+ val numbers = all(
+ task { 1L },
+ task { 2L },
+ task { throw runtimeException }
+ )
+
+ Assert.assertEquals(runtimeException, numbers.getError())
+ }
+
+ @Test
+ fun testAnySucceeds() {
+ val promise = any(
+ task {
+ TimeUnit.SECONDS.sleep(3)
+ 1L
+ },
+ task {
+ TimeUnit.SECONDS.sleep(2)
+ 2L
+ },
+ task {
+ TimeUnit.SECONDS.sleep(1)
+ 3L
+ }
+ )
+
+ Assert.assertTrue(promise.isDone())
+ Assert.assertTrue(promise.isSuccess())
+ Assert.assertFalse(promise.isFailure())
+ }
+
+ @Test
+ fun testAllFails() {
+ val runtimeException = RuntimeException()
+ val ioException = IOException()
+ val illegalStateException = IllegalStateException()
+ val promise = any(
+ task {
+ TimeUnit.SECONDS.sleep(3)
+ throw runtimeException
+ },
+ task {
+ TimeUnit.SECONDS.sleep(2)
+ throw ioException
+ },
+ task {
+ TimeUnit.SECONDS.sleep(1)
+ throw illegalStateException
+ }
+ )
+
+ Assert.assertTrue(promise.isDone())
+ Assert.assertFalse(promise.isSuccess())
+ Assert.assertTrue(promise.isFailure())
+ }
+
+ @Test
+ fun testSimpleCombine() {
+ val promise = task { 1L } and task { "Hello" }
+ val result = promise.get()
+
+ Assert.assertEquals(1L, result.first)
+ Assert.assertEquals("Hello", result.second)
+ }
+
+ @Test
+ fun testLongerCombine() {
+ val promise = combine(
+ task { 1L },
+ task { "Hello" },
+ task { Currency.getInstance("USD") }
+ )
+ val result = promise.get()
+
+ Assert.assertEquals(1L, result.first)
+ Assert.assertEquals("Hello", result.second)
+ Assert.assertEquals(Currency.getInstance("USD"), result.third)
+ }
+}
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTimeoutTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTimeoutTest.kt
new file mode 100644
index 0000000000..e37d2cc2fa
--- /dev/null
+++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTimeoutTest.kt
@@ -0,0 +1,38 @@
+package com.baeldung.kotlin
+
+import nl.komponents.kovenant.Promise
+import nl.komponents.kovenant.any
+import nl.komponents.kovenant.task
+import org.junit.Assert
+import org.junit.Ignore
+import org.junit.Test
+
+@Ignore
+// Note that this can not run in the same test run if KovenantTest has already been executed
+class KovenantTimeoutTest {
+ @Test
+ fun testTimeout() {
+ val promise = timedTask(1000) { "Hello" }
+ val result = promise.get()
+ Assert.assertEquals("Hello", result)
+ }
+
+ @Test
+ fun testTimeoutExpired() {
+ val promise = timedTask(1000) {
+ Thread.sleep(3000)
+ "Hello"
+ }
+ val result = promise.get()
+ Assert.assertNull(result)
+ }
+
+ fun timedTask(millis: Long, body: () -> T) : Promise> {
+ val timeoutTask = task {
+ Thread.sleep(millis)
+ null
+ }
+ val activeTask = task(body = body)
+ return any(activeTask, timeoutTask)
+ }
+}
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/StringConcatenationTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/StringConcatenationTest.kt
new file mode 100644
index 0000000000..9c371614a4
--- /dev/null
+++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/StringConcatenationTest.kt
@@ -0,0 +1,48 @@
+package com.baeldung.kotlin
+
+import org.junit.Test
+import kotlin.test.assertEquals
+
+class StringConcatenationTest {
+
+ @Test
+ fun givenTwoStrings_concatenateWithTemplates_thenEquals() {
+ val a = "Hello"
+ val b = "Baeldung"
+ val c = "$a $b"
+
+ assertEquals("Hello Baeldung", c)
+ }
+
+ @Test
+ fun givenTwoStrings_concatenateWithPlusOperator_thenEquals() {
+ val a = "Hello"
+ val b = "Baeldung"
+ val c = a + " " + b
+
+ assertEquals("Hello Baeldung", c)
+ }
+
+ @Test
+ fun givenTwoStrings_concatenateWithStringBuilder_thenEquals() {
+ val a = "Hello"
+ val b = "Baeldung"
+
+ val builder = StringBuilder()
+ builder.append(a).append(" ").append(b)
+
+ val c = builder.toString()
+
+ assertEquals("Hello Baeldung", c)
+ }
+
+ @Test
+ fun givenTwoStrings_concatenateWithPlusMethod_thenEquals() {
+ val a = "Hello"
+ val b = "Baeldung"
+ val c = a.plus(" ").plus(b)
+
+ assertEquals("Hello Baeldung", c)
+ }
+
+}
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/gson/GsonUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/gson/GsonUnitTest.kt
new file mode 100644
index 0000000000..bdf44d3b49
--- /dev/null
+++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/gson/GsonUnitTest.kt
@@ -0,0 +1,30 @@
+package com.baeldung.kotlin.gson
+
+import com.google.gson.Gson
+
+import org.junit.Assert
+import org.junit.Test
+
+class GsonUnitTest {
+
+ var gson = Gson()
+
+ @Test
+ fun givenObject_thenGetJSONString() {
+ var jsonString = gson.toJson(TestModel(1,"Test"))
+ Assert.assertEquals(jsonString, "{\"id\":1,\"description\":\"Test\"}")
+ }
+
+ @Test
+ fun givenJSONString_thenGetObject() {
+ var jsonString = "{\"id\":1,\"description\":\"Test\"}";
+ var testModel = gson.fromJson(jsonString, TestModel::class.java)
+ Assert.assertEquals(testModel.id, 1)
+ Assert.assertEquals(testModel.description, "Test")
+ }
+
+ data class TestModel(
+ val id: Int,
+ val description: String
+ )
+}
\ No newline at end of file
diff --git a/disruptor/pom.xml b/disruptor/pom.xml
index d3cef3bd9b..c26dcc0cd4 100644
--- a/disruptor/pom.xml
+++ b/disruptor/pom.xml
@@ -36,22 +36,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
org.apache.maven.plugins
maven-jar-plugin
diff --git a/drools/pom.xml b/drools/pom.xml
index 631bc8c792..009ac8acec 100644
--- a/drools/pom.xml
+++ b/drools/pom.xml
@@ -48,12 +48,18 @@
poi-ooxml
${apache-poi-version}
+
+ org.optaplanner
+ optaplanner-core
+ ${opta-planner-version}
+
4.4.6
7.4.1.Final
3.13
+ 7.10.0.Final
diff --git a/drools/src/main/java/com/baeldung/drools/optaplanner/CourseSchedule.java b/drools/src/main/java/com/baeldung/drools/optaplanner/CourseSchedule.java
new file mode 100644
index 0000000000..7b2ba117a1
--- /dev/null
+++ b/drools/src/main/java/com/baeldung/drools/optaplanner/CourseSchedule.java
@@ -0,0 +1,63 @@
+package com.baeldung.drools.optaplanner;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty;
+import org.optaplanner.core.api.domain.solution.PlanningScore;
+import org.optaplanner.core.api.domain.solution.PlanningSolution;
+import org.optaplanner.core.api.domain.solution.drools.ProblemFactCollectionProperty;
+import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
+import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@PlanningSolution
+public class CourseSchedule {
+
+ Logger logger = LoggerFactory.getLogger("CourseSchedule");
+
+ private List roomList;
+ private List periodList;
+ private List lectureList;
+ private HardSoftScore score;
+
+ public CourseSchedule(){
+ roomList = new ArrayList<>();
+ periodList = new ArrayList<>();
+ lectureList = new ArrayList<>();
+ }
+
+ @ValueRangeProvider(id = "availableRooms")
+ @ProblemFactCollectionProperty
+ public List getRoomList() {
+ return roomList;
+ }
+
+ @ValueRangeProvider(id = "availablePeriods")
+ @ProblemFactCollectionProperty
+ public List getPeriodList() {
+ return periodList;
+ }
+
+ @PlanningEntityCollectionProperty
+ public List getLectureList() {
+ return lectureList;
+ }
+
+ @PlanningScore
+ public HardSoftScore getScore() {
+ return score;
+ }
+
+ public void setScore(HardSoftScore score) {
+ this.score = score;
+ }
+
+ public void printCourseSchedule() {
+ lectureList.stream()
+ .map(c -> "Lecture in Room " + c.getRoomNumber().toString() + " during Period " + c.getPeriod().toString())
+ .forEach(k -> logger.info(k));
+ }
+
+}
diff --git a/drools/src/main/java/com/baeldung/drools/optaplanner/Lecture.java b/drools/src/main/java/com/baeldung/drools/optaplanner/Lecture.java
new file mode 100644
index 0000000000..193cdb08b1
--- /dev/null
+++ b/drools/src/main/java/com/baeldung/drools/optaplanner/Lecture.java
@@ -0,0 +1,30 @@
+package com.baeldung.drools.optaplanner;
+
+import org.optaplanner.core.api.domain.entity.PlanningEntity;
+import org.optaplanner.core.api.domain.variable.PlanningVariable;
+
+@PlanningEntity
+public class Lecture {
+
+ private Integer roomNumber;
+ private Integer period;
+
+ @PlanningVariable(valueRangeProviderRefs = {"availablePeriods"})
+ public Integer getPeriod() {
+ return period;
+ }
+
+ @PlanningVariable(valueRangeProviderRefs = {"availableRooms"})
+ public Integer getRoomNumber() {
+ return roomNumber;
+ }
+
+ public void setPeriod(Integer period) {
+ this.period = period;
+ }
+
+ public void setRoomNumber(Integer roomNumber) {
+ this.roomNumber = roomNumber;
+ }
+
+}
diff --git a/drools/src/main/java/com/baeldung/drools/optaplanner/ScoreCalculator.java b/drools/src/main/java/com/baeldung/drools/optaplanner/ScoreCalculator.java
new file mode 100644
index 0000000000..86501cdccd
--- /dev/null
+++ b/drools/src/main/java/com/baeldung/drools/optaplanner/ScoreCalculator.java
@@ -0,0 +1,32 @@
+package com.baeldung.drools.optaplanner;
+
+import java.util.HashSet;
+
+import org.optaplanner.core.api.score.Score;
+import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
+import org.optaplanner.core.impl.score.director.easy.EasyScoreCalculator;
+
+public class ScoreCalculator implements EasyScoreCalculator {
+
+ @Override
+ public Score calculateScore(CourseSchedule courseSchedule) {
+ int hardScore = 0;
+ int softScore = 0;
+
+ HashSet occupiedRooms = new HashSet<>();
+ for (Lecture lecture : courseSchedule.getLectureList()) {
+ if(lecture.getPeriod() != null && lecture.getRoomNumber() != null) {
+ String roomInUse = lecture.getPeriod().toString() + ":" + lecture.getRoomNumber().toString();
+ if (occupiedRooms.contains(roomInUse)) {
+ hardScore += -1;
+ } else {
+ occupiedRooms.add(roomInUse);
+ }
+ } else {
+ hardScore += -1;
+ }
+ }
+
+ return HardSoftScore.valueOf(hardScore, softScore);
+ }
+}
diff --git a/drools/src/main/resources/courseSchedule.drl b/drools/src/main/resources/courseSchedule.drl
new file mode 100644
index 0000000000..35dd57df84
--- /dev/null
+++ b/drools/src/main/resources/courseSchedule.drl
@@ -0,0 +1,14 @@
+package com.baeldung.drools.optaplanner
+
+import com.baeldung.drools.optaplanner.Lecture;
+import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;
+
+global HardSoftScoreHolder scoreHolder;
+
+rule "noNullRoomPeriod"
+ when
+ Lecture( roomNumber == null );
+ Lecture( period == null );
+ then
+ scoreHolder.addHardConstraintMatch(kcontext, -1);
+end
\ No newline at end of file
diff --git a/drools/src/main/resources/courseScheduleSolverConfigDrools.xml b/drools/src/main/resources/courseScheduleSolverConfigDrools.xml
new file mode 100644
index 0000000000..7cf95fdcd3
--- /dev/null
+++ b/drools/src/main/resources/courseScheduleSolverConfigDrools.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ courseSchedule.drl
+
+
+
+ 10
+
+
\ No newline at end of file
diff --git a/drools/src/main/resources/courseScheduleSolverConfiguration.xml b/drools/src/main/resources/courseScheduleSolverConfiguration.xml
new file mode 100644
index 0000000000..dfedb8f2fd
--- /dev/null
+++ b/drools/src/main/resources/courseScheduleSolverConfiguration.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ com.baeldung.drools.optaplanner.ScoreCalculator
+
+
+
+ 10
+
+
\ No newline at end of file
diff --git a/drools/src/test/java/com/baeldung/drools/optaplanner/OptaPlannerUnitTest.java b/drools/src/test/java/com/baeldung/drools/optaplanner/OptaPlannerUnitTest.java
new file mode 100644
index 0000000000..1880e30b86
--- /dev/null
+++ b/drools/src/test/java/com/baeldung/drools/optaplanner/OptaPlannerUnitTest.java
@@ -0,0 +1,49 @@
+package com.baeldung.drools.optaplanner;
+
+import java.util.Arrays;
+
+import org.junit.Assert;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.optaplanner.core.api.solver.Solver;
+import org.optaplanner.core.api.solver.SolverFactory;
+
+public class OptaPlannerUnitTest {
+
+ static CourseSchedule unsolvedCourseSchedule;
+
+ @BeforeAll
+ public static void setUp() {
+
+ unsolvedCourseSchedule = new CourseSchedule();
+
+ for(int i = 0; i < 10; i++){
+ unsolvedCourseSchedule.getLectureList().add(new Lecture());
+ }
+
+ unsolvedCourseSchedule.getPeriodList().addAll(Arrays.asList(new Integer[] { 1, 2, 3 }));
+ unsolvedCourseSchedule.getRoomList().addAll(Arrays.asList(new Integer[] { 1, 2 }));
+ }
+
+ @Test
+ public void test_whenCustomJavaSolver() {
+
+ SolverFactory solverFactory = SolverFactory.createFromXmlResource("courseScheduleSolverConfiguration.xml");
+ Solver solver = solverFactory.buildSolver();
+ CourseSchedule solvedCourseSchedule = solver.solve(unsolvedCourseSchedule);
+
+ Assert.assertNotNull(solvedCourseSchedule.getScore());
+ Assert.assertEquals(-4, solvedCourseSchedule.getScore().getHardScore());
+ }
+
+ @Test
+ public void test_whenDroolsSolver() {
+
+ SolverFactory solverFactory = SolverFactory.createFromXmlResource("courseScheduleSolverConfigDrools.xml");
+ Solver solver = solverFactory.buildSolver();
+ CourseSchedule solvedCourseSchedule = solver.solve(unsolvedCourseSchedule);
+
+ Assert.assertNotNull(solvedCourseSchedule.getScore());
+ Assert.assertEquals(0, solvedCourseSchedule.getScore().getHardScore());
+ }
+}
diff --git a/enterprise-patterns/README.md b/enterprise-patterns/README.md
deleted file mode 100644
index ff12555376..0000000000
--- a/enterprise-patterns/README.md
+++ /dev/null
@@ -1 +0,0 @@
-## Relevant articles:
diff --git a/enterprise-patterns/intercepting-filter-pattern/src/main/java/com/baeldung/enterprise/patterns/front/controller/filters/AuditFilter.java b/enterprise-patterns/intercepting-filter-pattern/src/main/java/com/baeldung/enterprise/patterns/front/controller/filters/AuditFilter.java
deleted file mode 100644
index d24c0a94b3..0000000000
--- a/enterprise-patterns/intercepting-filter-pattern/src/main/java/com/baeldung/enterprise/patterns/front/controller/filters/AuditFilter.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.baeldung.enterprise.patterns.front.controller.filters;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import java.io.IOException;
-
-public class AuditFilter extends BaseFilter {
- @Override
- public void doFilter(
- ServletRequest request,
- ServletResponse response,
- FilterChain chain
- ) throws IOException, ServletException {
- HttpServletRequest httpServletRequest = (HttpServletRequest) request;
- HttpSession session = httpServletRequest.getSession(false);
- if (session != null && session.getAttribute("username") != null) {
- request.setAttribute("username", session.getAttribute("username"));
- }
- chain.doFilter(request, response);
- }
-}
diff --git a/enterprise-patterns/intercepting-filter-pattern/src/main/java/com/baeldung/enterprise/patterns/front/controller/filters/VisitorCounterFilter.java b/enterprise-patterns/intercepting-filter-pattern/src/main/java/com/baeldung/enterprise/patterns/front/controller/filters/VisitorCounterFilter.java
deleted file mode 100644
index 0ae7cd73fd..0000000000
--- a/enterprise-patterns/intercepting-filter-pattern/src/main/java/com/baeldung/enterprise/patterns/front/controller/filters/VisitorCounterFilter.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.baeldung.enterprise.patterns.front.controller.filters;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.annotation.WebFilter;
-import java.io.IOException;
-
-@WebFilter(servletNames = "front-controller")
-public class VisitorCounterFilter extends BaseFilter {
- private int counter;
-
- @Override
- public void doFilter(
- ServletRequest request,
- ServletResponse response,
- FilterChain chain
- ) throws IOException, ServletException {
- request.setAttribute("counter", ++counter);
- chain.doFilter(request, response);
- }
-}
diff --git a/enterprise-patterns/pom.xml b/enterprise-patterns/pom.xml
deleted file mode 100644
index ffd0b66aad..0000000000
--- a/enterprise-patterns/pom.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
- 4.0.0
- com.baeldung.enterprise.patterns
- enterprise-patterns-parent
- pom
-
-
- com.baeldung
- parent-modules
- 1.0.0-SNAPSHOT
-
-
-
- spring-dispatcher-servlet
-
-
-
diff --git a/gson/README.md b/gson/README.md
index bedfbd206c..4122b21431 100644
--- a/gson/README.md
+++ b/gson/README.md
@@ -7,3 +7,4 @@
- [Gson Deserialization Cookbook](http://www.baeldung.com/gson-deserialization-guide)
- [Jackson vs Gson](http://www.baeldung.com/jackson-vs-gson)
- [Exclude Fields from Serialization in Gson](http://www.baeldung.com/gson-exclude-fields-serialization)
+- [Save Data to a JSON File with Gson](https://www.baeldung.com/gson-save-file)
diff --git a/guava/README.md b/guava/README.md
index bb4e225649..fe1a347d72 100644
--- a/guava/README.md
+++ b/guava/README.md
@@ -33,3 +33,4 @@
- [Using Guava CountingOutputStream](http://www.baeldung.com/guava-counting-outputstream)
- [Hamcrest Text Matchers](http://www.baeldung.com/hamcrest-text-matchers)
- [Quick Guide to the Guava RateLimiter](http://www.baeldung.com/guava-rate-limiter)
+- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
diff --git a/hazelcast/README.md b/hazelcast/README.md
index b90f66a8d0..7adb13f2af 100644
--- a/hazelcast/README.md
+++ b/hazelcast/README.md
@@ -1,2 +1,3 @@
### Relevant Articles:
- [Guide to Hazelcast with Java](http://www.baeldung.com/java-hazelcast)
+- [Introduction to Hazelcast Jet](https://www.baeldung.com/hazelcast-jet)
diff --git a/hibernate5/README.md b/hibernate5/README.md
index 1bce52bd5e..8f2f8eb469 100644
--- a/hibernate5/README.md
+++ b/hibernate5/README.md
@@ -13,3 +13,4 @@
- [Pessimistic Locking in JPA](http://www.baeldung.com/jpa-pessimistic-locking)
- [Bootstrapping JPA Programmatically in Java](http://www.baeldung.com/java-bootstrap-jpa)
- [Optimistic Locking in JPA](http://www.baeldung.com/jpa-optimistic-locking)
+- [Hibernate Entity Lifecycle](https://www.baeldung.com/hibernate-entity-lifecycle)
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java b/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java
index 23d7d2e201..2212e736ab 100644
--- a/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java
@@ -1,5 +1,11 @@
package com.baeldung.hibernate;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Properties;
+
+import com.baeldung.hibernate.entities.DeptEmployee;
import com.baeldung.hibernate.optimisticlocking.OptimisticLockingCourse;
import com.baeldung.hibernate.optimisticlocking.OptimisticLockingStudent;
import com.baeldung.hibernate.pessimisticlocking.Individual;
@@ -16,10 +22,30 @@ import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Properties;
+import com.baeldung.hibernate.pojo.Course;
+import com.baeldung.hibernate.pojo.Employee;
+import com.baeldung.hibernate.pojo.EntityDescription;
+import com.baeldung.hibernate.pojo.OrderEntry;
+import com.baeldung.hibernate.pojo.OrderEntryIdClass;
+import com.baeldung.hibernate.pojo.OrderEntryPK;
+import com.baeldung.hibernate.pojo.Person;
+import com.baeldung.hibernate.pojo.Phone;
+import com.baeldung.hibernate.pojo.PointEntity;
+import com.baeldung.hibernate.pojo.PolygonEntity;
+import com.baeldung.hibernate.pojo.Product;
+import com.baeldung.hibernate.pojo.Student;
+import com.baeldung.hibernate.pojo.TemporalValues;
+import com.baeldung.hibernate.pojo.User;
+import com.baeldung.hibernate.pojo.UserProfile;
+import com.baeldung.hibernate.pojo.inheritance.Animal;
+import com.baeldung.hibernate.pojo.inheritance.Bag;
+import com.baeldung.hibernate.pojo.inheritance.Book;
+import com.baeldung.hibernate.pojo.inheritance.Car;
+import com.baeldung.hibernate.pojo.inheritance.MyEmployee;
+import com.baeldung.hibernate.pojo.inheritance.MyProduct;
+import com.baeldung.hibernate.pojo.inheritance.Pen;
+import com.baeldung.hibernate.pojo.inheritance.Pet;
+import com.baeldung.hibernate.pojo.inheritance.Vehicle;
public class HibernateUtil {
private static SessionFactory sessionFactory;
@@ -72,6 +98,8 @@ public class HibernateUtil {
metadataSources.addAnnotatedClass(PessimisticLockingCourse.class);
metadataSources.addAnnotatedClass(com.baeldung.hibernate.pessimisticlocking.Customer.class);
metadataSources.addAnnotatedClass(com.baeldung.hibernate.pessimisticlocking.Address.class);
+ metadataSources.addAnnotatedClass(DeptEmployee.class);
+ metadataSources.addAnnotatedClass(com.baeldung.hibernate.entities.Department.class);
metadataSources.addAnnotatedClass(OptimisticLockingCourse.class);
metadataSources.addAnnotatedClass(OptimisticLockingStudent.class);
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/entities/Department.java b/hibernate5/src/main/java/com/baeldung/hibernate/entities/Department.java
new file mode 100644
index 0000000000..ff94f4f849
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/entities/Department.java
@@ -0,0 +1,45 @@
+package com.baeldung.hibernate.entities;
+
+import java.util.List;
+
+import javax.persistence.*;
+
+@Entity
+public class Department {
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE)
+ private long id;
+
+ private String name;
+
+ @OneToMany(mappedBy="department")
+ private List employees;
+
+ public Department(String name) {
+ this.name = name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List getEmployees() {
+ return employees;
+ }
+
+ public void setEmployees(List employees) {
+ this.employees = employees;
+ }
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/entities/DeptEmployee.java b/hibernate5/src/main/java/com/baeldung/hibernate/entities/DeptEmployee.java
new file mode 100644
index 0000000000..7a51009b62
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/entities/DeptEmployee.java
@@ -0,0 +1,65 @@
+package com.baeldung.hibernate.entities;
+
+import javax.persistence.*;
+
+@Entity
+public class DeptEmployee {
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE)
+ private long id;
+
+ private String employeeNumber;
+
+ private String designation;
+
+ private String name;
+
+ @ManyToOne
+ private Department department;
+
+ public DeptEmployee(String name, String employeeNumber, Department department) {
+ this.name = name;
+ this.employeeNumber = employeeNumber;
+ this.department = department;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getEmployeeNumber() {
+ return employeeNumber;
+ }
+
+ public void setEmployeeNumber(String employeeNumber) {
+ this.employeeNumber = employeeNumber;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Department getDepartment() {
+ return department;
+ }
+
+ public void setDepartment(Department department) {
+ this.department = department;
+ }
+
+ public String getDesignation() {
+ return designation;
+ }
+
+ public void setDesignation(String designation) {
+ this.designation = designation;
+ }
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Result.java b/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Result.java
new file mode 100644
index 0000000000..607269a267
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Result.java
@@ -0,0 +1,31 @@
+package com.baeldung.hibernate.pojo;
+
+public class Result {
+ private String employeeName;
+
+ private String departmentName;
+
+ public Result(String employeeName, String departmentName) {
+ this.employeeName = employeeName;
+ this.departmentName = departmentName;
+ }
+
+ public Result() {
+ }
+
+ public String getEmployeeName() {
+ return employeeName;
+ }
+
+ public void setEmployeeName(String employeeName) {
+ this.employeeName = employeeName;
+ }
+
+ public String getDepartmentName() {
+ return departmentName;
+ }
+
+ public void setDepartmentName(String departmentName) {
+ this.departmentName = departmentName;
+ }
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/proxy/BatchEmployee.java b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/BatchEmployee.java
new file mode 100644
index 0000000000..00643ab3dd
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/BatchEmployee.java
@@ -0,0 +1,56 @@
+package com.baeldung.hibernate.proxy;
+
+import org.hibernate.annotations.BatchSize;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Entity
+@BatchSize(size = 5)
+public class BatchEmployee implements Serializable {
+
+ @Id
+ @GeneratedValue (strategy = GenerationType.SEQUENCE)
+ private Long id;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ private Boss boss;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "surname")
+ private String surname;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Boss getBoss() {
+ return boss;
+ }
+
+ public void setBoss(Boss boss) {
+ this.boss = boss;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSurname() {
+ return surname;
+ }
+
+ public void setSurname(String surname) {
+ this.surname = surname;
+ }
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Boss.java b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Boss.java
new file mode 100644
index 0000000000..b6e01814d0
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Boss.java
@@ -0,0 +1,49 @@
+package com.baeldung.hibernate.proxy;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Entity
+public class Boss implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE)
+ private Long id;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "surname")
+ private String surname;
+
+ public Boss() { }
+
+ public Boss(String name, String surname) {
+ this.name = name;
+ this.surname = surname;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSurname() {
+ return surname;
+ }
+
+ public void setSurname(String surname) {
+ this.surname = surname;
+ }
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Employee.java b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Employee.java
new file mode 100644
index 0000000000..6bc64c35ef
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Employee.java
@@ -0,0 +1,53 @@
+package com.baeldung.hibernate.proxy;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Entity
+public class Employee implements Serializable {
+
+ @Id
+ @GeneratedValue (strategy = GenerationType.SEQUENCE)
+ private Long id;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ private Boss boss;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "surname")
+ private String surname;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Boss getBoss() {
+ return boss;
+ }
+
+ public void setBoss(Boss boss) {
+ this.boss = boss;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSurname() {
+ return surname;
+ }
+
+ public void setSurname(String surname) {
+ this.surname = surname;
+ }
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/proxy/HibernateUtil.java b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/HibernateUtil.java
new file mode 100644
index 0000000000..e6ad0432bd
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/HibernateUtil.java
@@ -0,0 +1,57 @@
+package com.baeldung.hibernate.proxy;
+
+import org.apache.commons.lang3.StringUtils;
+import org.hibernate.SessionFactory;
+import org.hibernate.boot.Metadata;
+import org.hibernate.boot.MetadataSources;
+import org.hibernate.boot.SessionFactoryBuilder;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.service.ServiceRegistry;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Properties;
+
+public class HibernateUtil {
+
+ private static SessionFactory sessionFactory;
+ private static String PROPERTY_FILE_NAME;
+
+ public static SessionFactory getSessionFactory(String propertyFileName) throws IOException {
+ PROPERTY_FILE_NAME = propertyFileName;
+ if (sessionFactory == null) {
+ ServiceRegistry serviceRegistry = configureServiceRegistry();
+ sessionFactory = getSessionFactoryBuilder(serviceRegistry).build();
+ }
+ return sessionFactory;
+ }
+
+ private static SessionFactoryBuilder getSessionFactoryBuilder(ServiceRegistry serviceRegistry) {
+ MetadataSources metadataSources = new MetadataSources(serviceRegistry);
+ metadataSources.addPackage("com.baeldung.hibernate.proxy");
+ metadataSources.addAnnotatedClass(Boss.class);
+ metadataSources.addAnnotatedClass(Employee.class);
+
+ Metadata metadata = metadataSources.buildMetadata();
+ return metadata.getSessionFactoryBuilder();
+
+ }
+
+ private static ServiceRegistry configureServiceRegistry() throws IOException {
+ Properties properties = getProperties();
+ return new StandardServiceRegistryBuilder().applySettings(properties)
+ .build();
+ }
+
+ private static Properties getProperties() throws IOException {
+ Properties properties = new Properties();
+ URL propertiesURL = Thread.currentThread()
+ .getContextClassLoader()
+ .getResource(StringUtils.defaultString(PROPERTY_FILE_NAME, "hibernate.properties"));
+ try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) {
+ properties.load(inputStream);
+ }
+ return properties;
+ }
+}
diff --git a/hibernate5/src/test/java/com/baeldung/hibernate/CustomClassIntegrationTest.java b/hibernate5/src/test/java/com/baeldung/hibernate/CustomClassIntegrationTest.java
new file mode 100644
index 0000000000..29ae55b773
--- /dev/null
+++ b/hibernate5/src/test/java/com/baeldung/hibernate/CustomClassIntegrationTest.java
@@ -0,0 +1,77 @@
+package com.baeldung.hibernate;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import java.util.List;
+
+import com.baeldung.hibernate.entities.DeptEmployee;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.query.Query;
+import org.hibernate.transform.Transformers;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.baeldung.hibernate.entities.Department;
+import com.baeldung.hibernate.pojo.Result;
+
+public class CustomClassIntegrationTest {
+
+ private Session session;
+
+ private Transaction transaction;
+
+ @BeforeEach
+ public void setUp() throws IOException {
+ session = HibernateUtil.getSessionFactory().openSession();
+ transaction = session.beginTransaction();
+ session.createNativeQuery("delete from manager").executeUpdate();
+ session.createNativeQuery("delete from department").executeUpdate();
+ Department department = new Department("Sales");
+ DeptEmployee employee = new DeptEmployee("John Smith", "001", department);
+ session.persist(department);
+ session.persist(employee);
+ transaction.commit();
+ transaction = session.beginTransaction();
+ }
+
+ @Test
+ public void whenAllManagersAreSelected_ThenObjectGraphIsReturned() {
+ Query query = session.createQuery("from com.baeldung.hibernate.entities.DeptEmployee");
+ List deptEmployees = query.list();
+ DeptEmployee deptEmployee = deptEmployees.get(0);
+ assertEquals("John Smith", deptEmployee.getName());
+ assertEquals("Sales", deptEmployee.getDepartment().getName());
+ }
+
+ @Test
+ public void whenIndividualPropertiesAreSelected_ThenObjectArrayIsReturned() {
+ Query query = session.createQuery("select m.name, m.department.name from com.baeldung.hibernate.entities.DeptEmployee m");
+ List managers = query.list();
+ Object[] manager = (Object[]) managers.get(0);
+ assertEquals("John Smith", manager[0]);
+ assertEquals("Sales", manager[1]);
+ }
+
+ @Test
+ public void whenResultConstructorInSelect_ThenListOfResultIsReturned() {
+ Query query = session.createQuery("select new com.baeldung.hibernate.pojo.Result(m.name, m.department.name) "
+ + "from DeptEmployee m");
+ List results = query.list();
+ Result result = results.get(0);
+ assertEquals("John Smith", result.getEmployeeName());
+ assertEquals("Sales", result.getDepartmentName());
+ }
+
+ @Test
+ public void whenResultTransformerOnQuery_ThenListOfResultIsReturned() {
+ Query query = session.createQuery("select m.name as employeeName, m.department.name as departmentName "
+ + "from com.baeldung.hibernate.entities.DeptEmployee m");
+ query.setResultTransformer(Transformers.aliasToBean(Result.class));
+ List results = query.list();
+ Result result = results.get(0);
+ assertEquals("John Smith", result.getEmployeeName());
+ assertEquals("Sales", result.getDepartmentName());
+ }
+}
diff --git a/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java b/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java
new file mode 100644
index 0000000000..fa41797dd2
--- /dev/null
+++ b/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java
@@ -0,0 +1,75 @@
+package com.baeldung.hibernate.proxy;
+
+import org.hibernate.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.junit.Assert.fail;
+
+public class HibernateProxyUnitTest {
+
+ private Session session;
+
+ @Before
+ public void init(){
+ try {
+ session = HibernateUtil.getSessionFactory("hibernate.properties")
+ .openSession();
+ } catch (HibernateException | IOException e) {
+ fail("Failed to initiate Hibernate Session [Exception:" + e.toString() + "]");
+ }
+
+ Boss boss = new Boss("Eduard", "Freud");
+ session.save(boss);
+ }
+
+ @After
+ public void close(){
+ if(session != null) {
+ session.close();
+ }
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void givenAnInexistentEmployeeId_whenUseGetMethod_thenReturnNull() {
+ Employee employee = session.get(Employee.class, new Long(14));
+ assertNull(employee);
+ employee.getId();
+ }
+
+ @Test
+ public void givenAnInexistentEmployeeId_whenUseLoadMethod_thenReturnAProxy() {
+ Employee employee = session.load(Employee.class, new Long(14));
+ assertNotNull(employee);
+ }
+
+ @Test
+ public void givenABatchEmployeeList_whenSaveOne_thenSaveTheWholeBatch() {
+ Transaction transaction = session.beginTransaction();
+
+ for (long i = 1; i <= 5; i++) {
+ Employee employee = new Employee();
+ employee.setName("Employee " + i);
+ session.save(employee);
+ }
+
+ //After this line is possible to see all the insertions in the logs
+ session.flush();
+ session.clear();
+ transaction.commit();
+
+ transaction = session.beginTransaction();
+
+ List employeeList = session.createQuery("from Employee")
+ .setCacheMode(CacheMode.IGNORE).getResultList();
+
+ assertEquals(employeeList.size(), 5);
+ transaction.commit();
+ }
+}
diff --git a/intelliJ/README.md b/intelliJ/README.md
new file mode 100644
index 0000000000..d45bd0cee5
--- /dev/null
+++ b/intelliJ/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles:
+
+- [Writing IntelliJ IDEA Plugins](https://www.baeldung.com/intellij-new-custom-plugin)
diff --git a/java-dates/pom.xml b/java-dates/pom.xml
index 877dd615a8..13e2a077e1 100644
--- a/java-dates/pom.xml
+++ b/java-dates/pom.xml
@@ -61,23 +61,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-
org.apache.maven.plugins
maven-compiler-plugin
diff --git a/java-numbers/pom.xml b/java-numbers/pom.xml
index bf4d3e8792..bb63c8cfe1 100644
--- a/java-numbers/pom.xml
+++ b/java-numbers/pom.xml
@@ -83,23 +83,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-
org.apache.maven.plugins
maven-javadoc-plugin
diff --git a/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java b/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java
new file mode 100644
index 0000000000..7de0197769
--- /dev/null
+++ b/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java
@@ -0,0 +1,29 @@
+package com.baeldung.maths;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+public class BigDecimalDemo {
+
+ /** Calculate total amount to be paid for an item rounded to cents..
+ * @param quantity
+ * @param unitPrice
+ * @param discountRate
+ * @param taxRate
+ * @return
+ */
+ public static BigDecimal calculateTotalAmount(BigDecimal quantity,
+ BigDecimal unitPrice, BigDecimal discountRate, BigDecimal taxRate) {
+ BigDecimal amount = quantity.multiply(unitPrice);
+ BigDecimal discount = amount.multiply(discountRate);
+ BigDecimal discountedAmount = amount.subtract(discount);
+ BigDecimal tax = discountedAmount.multiply(taxRate);
+ BigDecimal total = discountedAmount.add(tax);
+
+ // round to 2 decimal places using HALF_EVEN
+ BigDecimal roundedTotal = total.setScale(2, RoundingMode.HALF_EVEN);
+
+ return roundedTotal;
+ }
+
+}
diff --git a/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java b/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java
new file mode 100644
index 0000000000..2bf9872bec
--- /dev/null
+++ b/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java
@@ -0,0 +1,120 @@
+package com.baeldung.maths;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.util.Random;
+
+import org.junit.jupiter.api.Test;
+
+public class BigDecimalDemoUnitTest {
+
+ @Test
+ public void whenBigDecimalCreated_thenValueMatches() {
+ BigDecimal bdFromString = new BigDecimal("0.1");
+ BigDecimal bdFromCharArray = new BigDecimal(
+ new char[] { '3', '.', '1', '6', '1', '5' });
+ BigDecimal bdlFromInt = new BigDecimal(42);
+ BigDecimal bdFromLong = new BigDecimal(123412345678901L);
+ BigInteger bigInteger = BigInteger.probablePrime(100, new Random());
+ BigDecimal bdFromBigInteger = new BigDecimal(bigInteger);
+
+ assertEquals("0.1", bdFromString.toString());
+ assertEquals("3.1615", bdFromCharArray.toString());
+ assertEquals("42", bdlFromInt.toString());
+ assertEquals("123412345678901", bdFromLong.toString());
+ assertEquals(bigInteger.toString(), bdFromBigInteger.toString());
+ }
+
+ @Test
+ public void whenBigDecimalCreatedFromDouble_thenValueMayNotMatch() {
+ BigDecimal bdFromDouble = new BigDecimal(0.1d);
+ assertNotEquals("0.1", bdFromDouble.toString());
+ }
+
+ @Test
+ public void whenBigDecimalCreatedUsingValueOf_thenValueMatches() {
+ BigDecimal bdFromLong1 = BigDecimal.valueOf(123412345678901L);
+ BigDecimal bdFromLong2 = BigDecimal.valueOf(123412345678901L, 2);
+ BigDecimal bdFromDouble = BigDecimal.valueOf(0.1d);
+
+ assertEquals("123412345678901", bdFromLong1.toString());
+ assertEquals("1234123456789.01", bdFromLong2.toString());
+ assertEquals("0.1", bdFromDouble.toString());
+ }
+
+ @Test
+ public void whenEqualsCalled_thenSizeAndScaleMatched() {
+ BigDecimal bd1 = new BigDecimal("1.0");
+ BigDecimal bd2 = new BigDecimal("1.00");
+
+ assertFalse(bd1.equals(bd2));
+ }
+
+ @Test
+ public void whenComparingBigDecimals_thenExpectedResult() {
+ BigDecimal bd1 = new BigDecimal("1.0");
+ BigDecimal bd2 = new BigDecimal("1.00");
+ BigDecimal bd3 = new BigDecimal("2.0");
+
+ assertTrue(bd1.compareTo(bd3) < 0);
+ assertTrue(bd3.compareTo(bd1) > 0);
+ assertTrue(bd1.compareTo(bd2) == 0);
+ assertTrue(bd1.compareTo(bd3) <= 0);
+ assertTrue(bd1.compareTo(bd2) >= 0);
+ assertTrue(bd1.compareTo(bd3) != 0);
+ }
+
+ @Test
+ public void whenPerformingArithmetic_thenExpectedResult() {
+ BigDecimal bd1 = new BigDecimal("4.0");
+ BigDecimal bd2 = new BigDecimal("2.0");
+
+ BigDecimal sum = bd1.add(bd2);
+ BigDecimal difference = bd1.subtract(bd2);
+ BigDecimal quotient = bd1.divide(bd2);
+ BigDecimal product = bd1.multiply(bd2);
+
+ assertTrue(sum.compareTo(new BigDecimal("6.0")) == 0);
+ assertTrue(difference.compareTo(new BigDecimal("2.0")) == 0);
+ assertTrue(quotient.compareTo(new BigDecimal("2.0")) == 0);
+ assertTrue(product.compareTo(new BigDecimal("8.0")) == 0);
+ }
+
+ @Test
+ public void whenGettingAttributes_thenExpectedResult() {
+ BigDecimal bd = new BigDecimal("-12345.6789");
+
+ assertEquals(9, bd.precision());
+ assertEquals(4, bd.scale());
+ assertEquals(-1, bd.signum());
+ }
+
+ @Test
+ public void whenRoundingDecimal_thenExpectedResult() {
+ BigDecimal bd = new BigDecimal("2.5");
+ // Round to 1 digit using HALF_EVEN
+ BigDecimal rounded = bd
+ .round(new MathContext(1, RoundingMode.HALF_EVEN));
+
+ assertEquals("2", rounded.toString());
+ }
+
+ @Test
+ public void givenPurchaseTxn_whenCalculatingTotalAmount_thenExpectedResult() {
+ BigDecimal quantity = new BigDecimal("4.5");
+ BigDecimal unitPrice = new BigDecimal("2.69");
+ BigDecimal discountRate = new BigDecimal("0.10");
+ BigDecimal taxRate = new BigDecimal("0.0725");
+
+ BigDecimal amountToBePaid = BigDecimalDemo
+ .calculateTotalAmount(quantity, unitPrice, discountRate, taxRate);
+ assertEquals("11.68", amountToBePaid.toString());
+ }
+}
diff --git a/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java b/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java
new file mode 100644
index 0000000000..3537ccb3a3
--- /dev/null
+++ b/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java
@@ -0,0 +1,128 @@
+package com.baeldung.maths;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+import org.junit.jupiter.api.Test;
+
+public class BigIntegerDemoUnitTest {
+
+ @Test
+ public void whenBigIntegerCreatedFromConstructor_thenExpectedResult() {
+ BigInteger biFromString = new BigInteger("1234567890987654321");
+ BigInteger biFromByteArray = new BigInteger(
+ new byte[] { 64, 64, 64, 64, 64, 64 });
+ BigInteger biFromSignMagnitude = new BigInteger(-1,
+ new byte[] { 64, 64, 64, 64, 64, 64 });
+
+ assertEquals("1234567890987654321", biFromString.toString());
+ assertEquals("70644700037184", biFromByteArray.toString());
+ assertEquals("-70644700037184", biFromSignMagnitude.toString());
+ }
+
+ @Test
+ public void whenLongConvertedToBigInteger_thenValueMatches() {
+ BigInteger bi = BigInteger.valueOf(2305843009213693951L);
+
+ assertEquals("2305843009213693951", bi.toString());
+ }
+
+ @Test
+ public void givenBigIntegers_whentCompared_thenExpectedResult() {
+ BigInteger i = new BigInteger("123456789012345678901234567890");
+ BigInteger j = new BigInteger("123456789012345678901234567891");
+ BigInteger k = new BigInteger("123456789012345678901234567892");
+
+ assertTrue(i.compareTo(i) == 0);
+ assertTrue(j.compareTo(i) > 0);
+ assertTrue(j.compareTo(k) < 0);
+ }
+
+ @Test
+ public void givenBigIntegers_whenPerformingArithmetic_thenExpectedResult() {
+ BigInteger i = new BigInteger("4");
+ BigInteger j = new BigInteger("2");
+
+ BigInteger sum = i.add(j);
+ BigInteger difference = i.subtract(j);
+ BigInteger quotient = i.divide(j);
+ BigInteger product = i.multiply(j);
+
+ assertEquals(new BigInteger("6"), sum);
+ assertEquals(new BigInteger("2"), difference);
+ assertEquals(new BigInteger("2"), quotient);
+ assertEquals(new BigInteger("8"), product);
+ }
+
+ @Test
+ public void givenBigIntegers_whenPerformingBitOperations_thenExpectedResult() {
+ BigInteger i = new BigInteger("17");
+ BigInteger j = new BigInteger("7");
+
+ BigInteger and = i.and(j);
+ BigInteger or = i.or(j);
+ BigInteger not = j.not();
+ BigInteger xor = i.xor(j);
+ BigInteger andNot = i.andNot(j);
+ BigInteger shiftLeft = i.shiftLeft(1);
+ BigInteger shiftRight = i.shiftRight(1);
+
+ assertEquals(new BigInteger("1"), and);
+ assertEquals(new BigInteger("23"), or);
+ assertEquals(new BigInteger("-8"), not);
+ assertEquals(new BigInteger("22"), xor);
+ assertEquals(new BigInteger("16"), andNot);
+ assertEquals(new BigInteger("34"), shiftLeft);
+ assertEquals(new BigInteger("8"), shiftRight);
+ }
+
+ @Test
+ public void givenBigIntegers_whenPerformingBitManipulations_thenExpectedResult() {
+ BigInteger i = new BigInteger("1018");
+
+ int bitCount = i.bitCount();
+ int bitLength = i.bitLength();
+ int getLowestSetBit = i.getLowestSetBit();
+ boolean testBit3 = i.testBit(3);
+ BigInteger setBit12 = i.setBit(12);
+ BigInteger flipBit0 = i.flipBit(0);
+ BigInteger clearBit3 = i.clearBit(3);
+
+ assertEquals(8, bitCount);
+ assertEquals(10, bitLength);
+ assertEquals(1, getLowestSetBit);
+ assertEquals(true, testBit3);
+ assertEquals(new BigInteger("5114"), setBit12);
+ assertEquals(new BigInteger("1019"), flipBit0);
+ assertEquals(new BigInteger("1010"), clearBit3);
+ }
+
+ @Test
+ public void givenBigIntegers_whenModularCalculation_thenExpectedResult() {
+ BigInteger i = new BigInteger("31");
+ BigInteger j = new BigInteger("24");
+ BigInteger k = new BigInteger("16");
+
+ BigInteger gcd = j.gcd(k);
+ BigInteger multiplyAndmod = j.multiply(k)
+ .mod(i);
+ BigInteger modInverse = j.modInverse(i);
+ BigInteger modPow = j.modPow(k, i);
+
+ assertEquals(new BigInteger("8"), gcd);
+ assertEquals(new BigInteger("12"), multiplyAndmod);
+ assertEquals(new BigInteger("22"), modInverse);
+ assertEquals(new BigInteger("7"), modPow);
+ }
+
+ @Test
+ public void givenBigIntegers_whenPrimeOperations_thenExpectedResult() {
+ BigInteger i = BigInteger.probablePrime(100, new Random());
+
+ boolean isProbablePrime = i.isProbablePrime(1000);
+ assertEquals(true, isProbablePrime);
+ }
+}
diff --git a/java-streams/README.md b/java-streams/README.md
index 4bfcabb7cf..548d4b6a33 100644
--- a/java-streams/README.md
+++ b/java-streams/README.md
@@ -12,3 +12,4 @@
- [Iterable to Stream in Java](http://www.baeldung.com/java-iterable-to-stream)
- [How to Iterate Over a Stream With Indices](http://www.baeldung.com/java-stream-indices)
- [Primitive Type Streams in Java 8](http://www.baeldung.com/java-8-primitive-streams)
+- [Stream Ordering in Java](https://www.baeldung.com/java-stream-ordering)
diff --git a/java-streams/pom.xml b/java-streams/pom.xml
index 4f8651a756..023a5f695b 100644
--- a/java-streams/pom.xml
+++ b/java-streams/pom.xml
@@ -86,23 +86,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-
org.apache.maven.plugins
maven-compiler-plugin
diff --git a/java-streams/src/test/java/com/baeldung/streamordering/BenchmarkUnitTest.java b/java-streams/src/test/java/com/baeldung/streamordering/BenchmarkManualTest.java
similarity index 98%
rename from java-streams/src/test/java/com/baeldung/streamordering/BenchmarkUnitTest.java
rename to java-streams/src/test/java/com/baeldung/streamordering/BenchmarkManualTest.java
index ba1cb1f726..656a6d95f9 100644
--- a/java-streams/src/test/java/com/baeldung/streamordering/BenchmarkUnitTest.java
+++ b/java-streams/src/test/java/com/baeldung/streamordering/BenchmarkManualTest.java
@@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
-public class BenchmarkUnitTest
+public class BenchmarkManualTest
{
public void
diff --git a/java-strings/README.md b/java-strings/README.md
index d5b9b45b20..233d986d98 100644
--- a/java-strings/README.md
+++ b/java-strings/README.md
@@ -24,4 +24,6 @@
- [Check If a String Is Numeric in Java](http://www.baeldung.com/java-check-string-number)
- [Why Use char[] Array Over a String for Storing Passwords in Java?](http://www.baeldung.com/java-storing-passwords)
- [Convert a String to Title Case](http://www.baeldung.com/java-string-title-case)
-- [Compact Strings in Java 9](http://www.baeldung.com/java-9-compact-string)
\ No newline at end of file
+- [Compact Strings in Java 9](http://www.baeldung.com/java-9-compact-string)
+- [Java Check a String for Lowercase/Uppercase Letter, Special Character and Digit](https://www.baeldung.com/java-lowercase-uppercase-special-character-digit-regex)
+- [Convert java.util.Date to String](https://www.baeldung.com/java-util-date-to-string)
diff --git a/java-strings/pom.xml b/java-strings/pom.xml
index 0c83b4d9e7..29e992a2ce 100644
--- a/java-strings/pom.xml
+++ b/java-strings/pom.xml
@@ -52,6 +52,11 @@
icu4j
${icu4j.version}
+
+ com.google.guava
+ guava
+ ${guava.version}
+
com.vdurmont
@@ -71,23 +76,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-
org.apache.maven.plugins
maven-compiler-plugin
@@ -109,6 +97,7 @@
3.6.1
1.19
61.1
+ 26.0-jre