diff --git a/.travis.yml b/.travis.yml index 3a953a2e7b..3d28a5cd76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,8 @@ language: java before_install: - echo "MAVEN_OPTS='-Xmx2048M -Xss128M -XX:+CMSClassUnloadingEnabled -XX:+UseG1GC -XX:-UseGCOverheadLimit'" > ~/.mavenrc -install: travis_wait 60 mvn -q test -fae +install: skip +script: travis_wait 60 mvn -q test -fae sudo: required diff --git a/algorithms/pom.xml b/algorithms/pom.xml index e972f39494..2eb8cd42b6 100644 --- a/algorithms/pom.xml +++ b/algorithms/pom.xml @@ -39,6 +39,12 @@ jgrapht-core 1.0.1 + + org.assertj + assertj-core + 3.9.0 + test + diff --git a/algorithms/src/main/java/com/baeldung/algorithms/kthlargest/FindKthLargest.java b/algorithms/src/main/java/com/baeldung/algorithms/kthlargest/FindKthLargest.java new file mode 100644 index 0000000000..822abdae02 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/kthlargest/FindKthLargest.java @@ -0,0 +1,111 @@ +package com.baeldung.algorithms.kthlargest; + +import java.util.Arrays; +import java.util.Collections; +import java.util.stream.IntStream; + +public class FindKthLargest { + + public int findKthLargestBySorting(Integer[] arr, int k) { + Arrays.sort(arr); + int targetIndex = arr.length - k; + return arr[targetIndex]; + } + + public int findKthLargestBySortingDesc(Integer[] arr, int k) { + Arrays.sort(arr, Collections.reverseOrder()); + return arr[k - 1]; + } + + public int findKthElementByQuickSelect(Integer[] arr, int left, int right, int k) { + if (k >= 0 && k <= right - left + 1) { + int pos = partition(arr, left, right); + if (pos - left == k) { + return arr[pos]; + } + if (pos - left > k) { + return findKthElementByQuickSelect(arr, left, pos - 1, k); + } + return findKthElementByQuickSelect(arr, pos + 1, right, k - pos + left - 1); + } + return 0; + } + + public int findKthElementByQuickSelectWithIterativePartition(Integer[] arr, int left, int right, int k) { + if (k >= 0 && k <= right - left + 1) { + int pos = partitionIterative(arr, left, right); + if (pos - left == k) { + return arr[pos]; + } + if (pos - left > k) { + return findKthElementByQuickSelectWithIterativePartition(arr, left, pos - 1, k); + } + return findKthElementByQuickSelectWithIterativePartition(arr, pos + 1, right, k - pos + left - 1); + } + return 0; + } + + private int partition(Integer[] arr, int left, int right) { + int pivot = arr[right]; + Integer[] leftArr; + Integer[] rightArr; + + leftArr = IntStream.range(left, right) + .filter(i -> arr[i] < pivot) + .map(i -> arr[i]) + .boxed() + .toArray(Integer[]::new); + + rightArr = IntStream.range(left, right) + .filter(i -> arr[i] > pivot) + .map(i -> arr[i]) + .boxed() + .toArray(Integer[]::new); + + int leftArraySize = leftArr.length; + System.arraycopy(leftArr, 0, arr, left, leftArraySize); + arr[leftArraySize + left] = pivot; + System.arraycopy(rightArr, 0, arr, left + leftArraySize + 1, rightArr.length); + + return left + leftArraySize; + } + + private int partitionIterative(Integer[] arr, int left, int right) { + int pivot = arr[right], i = left; + for (int j = left; j <= right - 1; j++) { + if (arr[j] <= pivot) { + swap(arr, i, j); + i++; + } + } + swap(arr, i, right); + return i; + } + + public int findKthElementByRandomizedQuickSelect(Integer[] arr, int left, int right, int k) { + if (k >= 0 && k <= right - left + 1) { + int pos = randomPartition(arr, left, right); + if (pos - left == k) { + return arr[pos]; + } + if (pos - left > k) { + return findKthElementByRandomizedQuickSelect(arr, left, pos - 1, k); + } + return findKthElementByRandomizedQuickSelect(arr, pos + 1, right, k - pos + left - 1); + } + return 0; + } + + private int randomPartition(Integer arr[], int left, int right) { + int n = right - left + 1; + int pivot = (int) (Math.random()) % n; + swap(arr, left + pivot, right); + return partition(arr, left, right); + } + + private void swap(Integer[] arr, int n1, int n2) { + int temp = arr[n2]; + arr[n2] = arr[n1]; + arr[n1] = temp; + } +} diff --git a/algorithms/src/test/java/com/baeldung/algorithms/kthlargest/FindKthLargestUnitTest.java b/algorithms/src/test/java/com/baeldung/algorithms/kthlargest/FindKthLargestUnitTest.java new file mode 100644 index 0000000000..6fbb7c163a --- /dev/null +++ b/algorithms/src/test/java/com/baeldung/algorithms/kthlargest/FindKthLargestUnitTest.java @@ -0,0 +1,57 @@ +package com.baeldung.algorithms.kthlargest; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.Before; +import org.junit.Test; + +public class FindKthLargestUnitTest { + + private FindKthLargest findKthLargest; + private Integer[] arr = { 3, 7, 1, 2, 8, 10, 4, 5, 6, 9 }; + + @Before + public void setup() { + findKthLargest = new FindKthLargest(); + } + + @Test + public void givenIntArray_whenFindKthLargestBySorting_thenGetResult() { + int k = 3; + assertThat(findKthLargest.findKthLargestBySorting(arr, k)).isEqualTo(8); + } + + @Test + public void givenIntArray_whenFindKthLargestBySortingDesc_thenGetResult() { + int k = 3; + assertThat(findKthLargest.findKthLargestBySortingDesc(arr, k)).isEqualTo(8); + } + + @Test + public void givenIntArray_whenFindKthLargestByQuickSelect_thenGetResult() { + int k = 3; + int kthLargest = arr.length - k; + assertThat(findKthLargest.findKthElementByQuickSelect(arr, 0, arr.length - 1, kthLargest)).isEqualTo(8); + } + + @Test + public void givenIntArray_whenFindKthElementByQuickSelectIterative_thenGetResult() { + int k = 3; + int kthLargest = arr.length - k; + assertThat(findKthLargest.findKthElementByQuickSelectWithIterativePartition(arr, 0, arr.length - 1, kthLargest)).isEqualTo(8); + } + + @Test + public void givenIntArray_whenFindKthSmallestByQuickSelect_thenGetResult() { + int k = 3; + assertThat(findKthLargest.findKthElementByQuickSelect(arr, 0, arr.length - 1, k - 1)).isEqualTo(3); + } + + @Test + public void givenIntArray_whenFindKthLargestByRandomizedQuickSelect_thenGetResult() { + int k = 3; + int kthLargest = arr.length - k; + assertThat(findKthLargest.findKthElementByRandomizedQuickSelect(arr, 0, arr.length - 1, kthLargest)).isEqualTo(8); + } + +} diff --git a/core-java-8/src/main/java/com/baeldung/streamApi/Product.java b/core-java-8/src/main/java/com/baeldung/stream/Product.java similarity index 96% rename from core-java-8/src/main/java/com/baeldung/streamApi/Product.java rename to core-java-8/src/main/java/com/baeldung/stream/Product.java index 1b7478551f..e99a969b81 100644 --- a/core-java-8/src/main/java/com/baeldung/streamApi/Product.java +++ b/core-java-8/src/main/java/com/baeldung/stream/Product.java @@ -1,4 +1,4 @@ -package com.baeldung.streamApi; +package com.baeldung.stream; import java.util.List; import java.util.stream.Stream; diff --git a/core-java-8/src/main/java/com/baeldung/stream/StreamApi.java b/core-java-8/src/main/java/com/baeldung/stream/StreamApi.java index 364fdeffbb..f0d5f1aa7e 100644 --- a/core-java-8/src/main/java/com/baeldung/stream/StreamApi.java +++ b/core-java-8/src/main/java/com/baeldung/stream/StreamApi.java @@ -16,7 +16,7 @@ public class StreamApi { } public static String getLastElementUsingSkip(List valueList) { - long count = valueList.stream().count(); + long count = (long) valueList.size(); Stream stream = valueList.stream(); return stream.skip(count - 1).findFirst().orElse(null); } diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8StreamApiUnitTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8StreamApiUnitTest.java index 73a10a57f4..5005cf7f47 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/Java8StreamApiUnitTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8StreamApiUnitTest.java @@ -1,6 +1,6 @@ package com.baeldung.java8; -import com.baeldung.streamApi.Product; +import com.baeldung.stream.Product; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; diff --git a/core-java-8/src/test/java/com/baeldung/stream/PrimitiveStreamsUnitTest.java b/core-java-8/src/test/java/com/baeldung/stream/PrimitiveStreamsUnitTest.java index c28d6300e0..2c88dc5ec7 100644 --- a/core-java-8/src/test/java/com/baeldung/stream/PrimitiveStreamsUnitTest.java +++ b/core-java-8/src/test/java/com/baeldung/stream/PrimitiveStreamsUnitTest.java @@ -6,6 +6,7 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; +import java.util.stream.Stream; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -65,7 +66,9 @@ public class PrimitiveStreamsUnitTest { @Test public void givenAnArrayWhenSumIsCalledThenTheCorrectSumIsReturned() { - int sum = Arrays.asList(33,45).stream().mapToInt(a -> a).sum(); + int sum = Stream.of(33,45) + .mapToInt(i -> i) + .sum(); assertEquals(78, sum); } diff --git a/core-java/README.md b/core-java/README.md index b965d25f88..94d203533e 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -131,4 +131,5 @@ - [How to Invert an Array in Java](http://www.baeldung.com/java-invert-array) - [Guide to the Cipher Class](http://www.baeldung.com/java-cipher-class) - [A Guide to Java Initialization](http://www.baeldung.com/java-initialization) - +- [Implementing a Binary Tree in Java](http://www.baeldung.com/java-binary-tree) +- [A Guide to ThreadLocalRandom in Java](http://www.baeldung.com/java-thread-local-random) diff --git a/core-java/pom.xml b/core-java/pom.xml index f99e4d68cf..5c1e9fcad0 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -389,6 +389,16 @@ + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.0-M1 + + 1.8 + 1.8 + + diff --git a/core-java/src/main/java/com/baeldung/javadoc/Person.java b/core-java/src/main/java/com/baeldung/javadoc/Person.java new file mode 100644 index 0000000000..5efb410de4 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/javadoc/Person.java @@ -0,0 +1,22 @@ +package com.baeldung.javadoc; + +public class Person { + /** + * This is a first name + */ + private String firstName; + private String lastName; + + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } +} diff --git a/core-java/src/main/java/com/baeldung/javadoc/SuperHero.java b/core-java/src/main/java/com/baeldung/javadoc/SuperHero.java new file mode 100644 index 0000000000..029a779cdb --- /dev/null +++ b/core-java/src/main/java/com/baeldung/javadoc/SuperHero.java @@ -0,0 +1,64 @@ +package com.baeldung.javadoc; + +/** + * Hero is the main entity we will be using to . . . + * @author Captain America + * + */ +public class SuperHero extends Person { + + /** + * The public name of a hero that is common knowledge + */ + private String heroName; + private String uniquePower; + private int health; + private int defense; + + /** + *

This is a simple description of the method. . . + * Superman! + *

+ * @param incomingDamage the amount of incoming damage + * @return the amount of health hero has after attack + * @see HERO-402 + * @since 1.0 + */ + public int successfullyAttacked(int incomingDamage, String damageType) { + // do things + return 0; + } + + public String getHeroName() { + return heroName; + } + + public void setHeroName(String heroName) { + this.heroName = heroName; + } + + public String getUniquePower() { + return uniquePower; + } + + public void setUniquePower(String uniquePower) { + this.uniquePower = uniquePower; + } + + public int getHealth() { + return health; + } + + public void setHealth(int health) { + this.health = health; + } + + public int getDefense() { + return defense; + } + + public void setDefense(int defense) { + this.defense = defense; + } + +} diff --git a/core-java/src/main/java/com/baeldung/socket/EchoMultiServer.java b/core-java/src/main/java/com/baeldung/socket/EchoMultiServer.java index a9f055f8f4..d2f9f0459c 100644 --- a/core-java/src/main/java/com/baeldung/socket/EchoMultiServer.java +++ b/core-java/src/main/java/com/baeldung/socket/EchoMultiServer.java @@ -16,7 +16,7 @@ public class EchoMultiServer { try { serverSocket = new ServerSocket(port); while (true) - new EchoClientHandler(serverSocket.accept()).run(); + new EchoClientHandler(serverSocket.accept()).start(); } catch (IOException e) { e.printStackTrace(); diff --git a/core-java/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarkRunner.java b/core-java/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarkRunner.java new file mode 100644 index 0000000000..e9c8056ff5 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarkRunner.java @@ -0,0 +1,22 @@ +package com.baeldung.threadlocalrandom; + +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +public class ThreadLocalRandomBenchMarkRunner { + + public static void main(String[] args) throws Exception { + + Options options = new OptionsBuilder().include(ThreadLocalRandomBenchMarker.class.getSimpleName()) + .threads(1) + .forks(1) + .shouldFailOnError(true) + .shouldDoGC(true) + .jvmArgs("-server") + .build(); + + new Runner(options).run(); + + } +} diff --git a/core-java/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarker.java b/core-java/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarker.java new file mode 100644 index 0000000000..8a0e2d2826 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarker.java @@ -0,0 +1,64 @@ +package com.baeldung.threadlocalrandom; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 1) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Benchmark) +public class ThreadLocalRandomBenchMarker { + + List> randomCallables = new ArrayList<>(); + List> threadLocalRandomCallables = new ArrayList<>(); + + @Setup(Level.Iteration) + public void init() { + Random random = new Random(); + randomCallables = new ArrayList<>(); + threadLocalRandomCallables = new ArrayList<>(); + for (int i = 0; i < 1000; i++) { + randomCallables.add(() -> { + return random.nextInt(); + }); + } + + for (int i = 0; i < 1000; i++) { + threadLocalRandomCallables.add(() -> { + return ThreadLocalRandom.current() + .nextInt(); + }); + } + } + + @Benchmark + public void randomValuesUsingRandom() throws InterruptedException { + ExecutorService executor = Executors.newWorkStealingPool(); + executor.invokeAll(randomCallables); + executor.shutdown(); + } + + @Benchmark + public void randomValuesUsingThreadLocalRandom() throws InterruptedException { + ExecutorService executor = Executors.newWorkStealingPool(); + executor.invokeAll(threadLocalRandomCallables); + executor.shutdown(); + } + +} diff --git a/hibernate5/README.md b/hibernate5/README.md index d480a7455c..1eb090f05d 100644 --- a/hibernate5/README.md +++ b/hibernate5/README.md @@ -4,3 +4,4 @@ - [An Overview of Identifiers in Hibernate](http://www.baeldung.com/hibernate-identifiers) - [Hibernate – Mapping Date and Time](http://www.baeldung.com/hibernate-date-time) - [Hibernate Inheritance Mapping](http://www.baeldung.com/hibernate-inheritance) +- [A Guide to Multitenancy in Hibernate 5](http://www.baeldung.com/hibernate-5-multitenancy) diff --git a/java-lite/README.md b/java-lite/README.md new file mode 100644 index 0000000000..bcb84e186e --- /dev/null +++ b/java-lite/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [RESTFul CRUD application with JavaLite] () \ No newline at end of file diff --git a/java-lite/pom.xml b/java-lite/pom.xml new file mode 100644 index 0000000000..554819f6e4 --- /dev/null +++ b/java-lite/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + + org.baeldung + java-lite + 1.0-SNAPSHOT + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + 9.3.4.RC1 + 1.4.13 + 1.15 + 5.1.45 + 1.7.0 + 1.8.2 + 4.11 + + + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty.maven.plugin.version} + + + + activejdbc.log + + + + active_reload + true + + + activeweb.log.request + true + + + + + + + org.javalite + activejdbc-instrumentation + ${activejdbc.version} + + + process-classes + + instrument + + + + + + + + + + org.javalite + activeweb + ${activeweb.version} + + + + mysql + mysql-connector-java + ${mysql.connector.java.version} + + + + com.sun + tools + ${sun.tools.version} + system + ${java.home}/../lib/tools.jar + + + + org.codehaus.jackson + jackson-core-lgpl + ${jackson.version} + + + org.codehaus.jackson + jackson-mapper-lgpl + ${jackson.version} + + + junit + junit + ${junit.version} + + + + \ No newline at end of file diff --git a/java-lite/src/main/java/app/config/AppBootstrap.java b/java-lite/src/main/java/app/config/AppBootstrap.java new file mode 100644 index 0000000000..7a87c2d0a7 --- /dev/null +++ b/java-lite/src/main/java/app/config/AppBootstrap.java @@ -0,0 +1,9 @@ +package app.config; + +import org.javalite.activeweb.AppContext; +import org.javalite.activeweb.Bootstrap; + +public class AppBootstrap extends Bootstrap { + public void init(AppContext context) { + } +} diff --git a/java-lite/src/main/java/app/config/AppControllerConfig.java b/java-lite/src/main/java/app/config/AppControllerConfig.java new file mode 100644 index 0000000000..42b7e728ec --- /dev/null +++ b/java-lite/src/main/java/app/config/AppControllerConfig.java @@ -0,0 +1,15 @@ +package app.config; + +import app.controllers.ProductsController; +import org.javalite.activeweb.AbstractControllerConfig; +import org.javalite.activeweb.AppContext; +import org.javalite.activeweb.controller_filters.DBConnectionFilter; +import org.javalite.activeweb.controller_filters.TimingFilter; + +public class AppControllerConfig extends AbstractControllerConfig { + @Override + public void init(AppContext appContext) { + addGlobalFilters(new TimingFilter()); + add(new DBConnectionFilter()).to(ProductsController.class); + } +} diff --git a/java-lite/src/main/java/app/config/DbConfig.java b/java-lite/src/main/java/app/config/DbConfig.java new file mode 100644 index 0000000000..25ba378b22 --- /dev/null +++ b/java-lite/src/main/java/app/config/DbConfig.java @@ -0,0 +1,11 @@ +package app.config; + +import org.javalite.activeweb.AbstractDBConfig; +import org.javalite.activeweb.AppContext; + +public class DbConfig extends AbstractDBConfig { + @Override + public void init(AppContext appContext) { + this.configFile("/database.properties"); + } +} diff --git a/java-lite/src/main/java/app/controllers/ProductsController.java b/java-lite/src/main/java/app/controllers/ProductsController.java new file mode 100644 index 0000000000..f68dd9a013 --- /dev/null +++ b/java-lite/src/main/java/app/controllers/ProductsController.java @@ -0,0 +1,101 @@ +package app.controllers; + +import app.models.Product; +import org.codehaus.jackson.map.ObjectMapper; +import org.javalite.activeweb.AppController; +import org.javalite.activeweb.annotations.RESTful; + +import java.util.Map; + +@RESTful +public class ProductsController extends AppController { + + public void index() { + try { + view("products", Product.findAll()); + render().contentType("application/json"); + } catch (Exception e) { + view("message", "There was an error.", "code", 200); + render("message"); + } + } + + public void create() { + try { + Map payload = new ObjectMapper().readValue(getRequestString(), Map.class); + Product p = new Product(); + p.fromMap(payload); + p.saveIt(); + view("message", "Successfully saved product id " + p.get("id"), "code", 200); + render("message"); + } catch (Exception e) { + view("message", "There was an error.", "code", 200); + render("message"); + } + } + + public void update() { + try { + Map payload = new ObjectMapper().readValue(getRequestString(), Map.class); + String id = getId(); + Product p = Product.findById(id); + if (p == null) { + view("message", "Product id " + id + " not found.", "code", 200); + render("message"); + return; + } + p.fromMap(payload); + p.saveIt(); + view("message", "Successfully updated product id " + id, "code", 200); + render("message"); + } catch (Exception e) { + view("message", "There was an error.", "code", 200); + render("message"); + } + } + + public void show() { + try { + String id = getId(); + Product p = Product.findById(id); + if (p == null) { + view("message", "Product id " + id + " not found.", "code", 200); + render("message"); + return; + } + view("product", p); + render("_product"); + } catch (Exception e) { + view("message", "There was an error.", "code", 200); + render("message"); + } + } + + public void destroy() { + try { + String id = getId(); + Product p = Product.findById(id); + if (p == null) { + view("message", "Product id " + id + " not found.", "code", 200); + render("message"); + return; + } + p.delete(); + view("message", "Successfully deleted product id " + id, "code", 200); + render("message"); + } catch (Exception e) { + view("message", "There was an error.", "code", 200); + render("message"); + } + } + + @Override + protected String getContentType() { + return "application/json"; + } + + @Override + protected String getLayout() { + return null; + } +} diff --git a/java-lite/src/main/java/app/models/Product.java b/java-lite/src/main/java/app/models/Product.java new file mode 100644 index 0000000000..7fa32b75d9 --- /dev/null +++ b/java-lite/src/main/java/app/models/Product.java @@ -0,0 +1,7 @@ +package app.models; + +import org.javalite.activejdbc.Model; + +public class Product extends Model { + +} diff --git a/java-lite/src/main/resources/database.properties b/java-lite/src/main/resources/database.properties new file mode 100644 index 0000000000..55b3851d33 --- /dev/null +++ b/java-lite/src/main/resources/database.properties @@ -0,0 +1,4 @@ +development.driver=com.mysql.jdbc.Driver +development.username=user +development.password=password +development.url=jdbc:mysql://localhost/dbname \ No newline at end of file diff --git a/java-lite/src/main/webapp/WEB-INF/views/products/_comma.ftl b/java-lite/src/main/webapp/WEB-INF/views/products/_comma.ftl new file mode 100644 index 0000000000..41622b4720 --- /dev/null +++ b/java-lite/src/main/webapp/WEB-INF/views/products/_comma.ftl @@ -0,0 +1 @@ +, \ No newline at end of file diff --git a/java-lite/src/main/webapp/WEB-INF/views/products/_product.ftl b/java-lite/src/main/webapp/WEB-INF/views/products/_product.ftl new file mode 100644 index 0000000000..562af0499e --- /dev/null +++ b/java-lite/src/main/webapp/WEB-INF/views/products/_product.ftl @@ -0,0 +1,4 @@ +{ +"id" : ${product.id}, +"name" : "${product.name}" +} \ No newline at end of file diff --git a/java-lite/src/main/webapp/WEB-INF/views/products/index.ftl b/java-lite/src/main/webapp/WEB-INF/views/products/index.ftl new file mode 100644 index 0000000000..c343f20910 --- /dev/null +++ b/java-lite/src/main/webapp/WEB-INF/views/products/index.ftl @@ -0,0 +1 @@ +[<@render partial="product" collection=products spacer="comma"/>] \ No newline at end of file diff --git a/java-lite/src/main/webapp/WEB-INF/views/products/message.ftl b/java-lite/src/main/webapp/WEB-INF/views/products/message.ftl new file mode 100644 index 0000000000..3e7faf1459 --- /dev/null +++ b/java-lite/src/main/webapp/WEB-INF/views/products/message.ftl @@ -0,0 +1,4 @@ +{ +"message" : "${message}", +"code" : ${code} +} \ No newline at end of file diff --git a/java-lite/src/main/webapp/WEB-INF/web.xml b/java-lite/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..c285876c86 --- /dev/null +++ b/java-lite/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,25 @@ + + + + + + dispatcher + org.javalite.activeweb.RequestDispatcher + + exclusions + css,images,js,ico + + + encoding + UTF-8 + + + + + + dispatcher + /* + + + diff --git a/java-lite/src/test/java/app/models/ProductTest.java b/java-lite/src/test/java/app/models/ProductTest.java new file mode 100644 index 0000000000..f6ee0a3d0a --- /dev/null +++ b/java-lite/src/test/java/app/models/ProductTest.java @@ -0,0 +1,25 @@ +package app.models; + +import org.javalite.activejdbc.Base; +import org.junit.Assert; +import org.junit.Test; + +public class ProductTest { + + //@Test + public void givenSavedProduct_WhenFindFirst_ThenSavedProductIsReturned() { + //Open DB connection + Base.open("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/dbname", "user", "password"); + + //Create a product and save it + Product toSaveProduct = new Product(); + toSaveProduct.set("name", "Bread"); + toSaveProduct.saveIt(); + + //Find product + Product savedProduct = Product.findFirst("name = ?", "Bread"); + + Assert.assertEquals(toSaveProduct.get("name"), savedProduct.get("name")); + } + +} \ No newline at end of file diff --git a/persistence-modules/java-cockroachdb/README.md b/persistence-modules/java-cockroachdb/README.md new file mode 100644 index 0000000000..0f0381212d --- /dev/null +++ b/persistence-modules/java-cockroachdb/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Guide to CockroachDB in Java](http://www.baeldung.com/) diff --git a/persistence-modules/java-cockroachdb/pom.xml b/persistence-modules/java-cockroachdb/pom.xml new file mode 100644 index 0000000000..2b6f9651bc --- /dev/null +++ b/persistence-modules/java-cockroachdb/pom.xml @@ -0,0 +1,74 @@ + + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + ../../ + + + 4.0.0 + + com.baeldung + java-cockroachdb + 1.0-SNAPSHOT + + + 42.1.4 + + + + + org.postgresql + postgresql + ${postgresql.version} + + + + + + integration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*ManualTest.java + + + **/*IntegrationTest.java + + + + + + + json + + + + + + + + + + + Central + Central + http://repo1.maven.org/maven2/ + default + + + \ No newline at end of file diff --git a/persistence-modules/java-cockroachdb/src/main/java/com/baeldung/cockroachdb/domain/Article.java b/persistence-modules/java-cockroachdb/src/main/java/com/baeldung/cockroachdb/domain/Article.java new file mode 100644 index 0000000000..dcc9dfb5b7 --- /dev/null +++ b/persistence-modules/java-cockroachdb/src/main/java/com/baeldung/cockroachdb/domain/Article.java @@ -0,0 +1,43 @@ +package com.baeldung.cockroachdb.domain; + +import java.util.UUID; + +public class Article { + + private UUID id; + + private String title; + + private String author; + + public Article(UUID id, String title, String author) { + this.id = id; + this.title = title; + this.author = author; + } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + +} diff --git a/persistence-modules/java-cockroachdb/src/main/java/com/baeldung/cockroachdb/repository/ArticleRepository.java b/persistence-modules/java-cockroachdb/src/main/java/com/baeldung/cockroachdb/repository/ArticleRepository.java new file mode 100644 index 0000000000..a37c19e397 --- /dev/null +++ b/persistence-modules/java-cockroachdb/src/main/java/com/baeldung/cockroachdb/repository/ArticleRepository.java @@ -0,0 +1,172 @@ +package com.baeldung.cockroachdb.repository; + +import com.baeldung.cockroachdb.domain.Article; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * Repository for the articles table related operations + */ +public class ArticleRepository { + + private static final String TABLE_NAME = "articles"; + private Connection connection; + + public ArticleRepository(Connection connection) { + this.connection = connection; + } + + /** + * Creates the articles table. + */ + public void createTable() throws SQLException { + StringBuilder sb = new StringBuilder("CREATE TABLE IF NOT EXISTS ").append(TABLE_NAME) + .append("(id uuid PRIMARY KEY, ") + .append("title string,") + .append("author string)"); + + final String query = sb.toString(); + Statement stmt = connection.createStatement(); + stmt.execute(query); + } + + /** + * Alter the articles table adding a column + * + * @param columnName Column name of the additional column + * @param columnType Column type of the additional column + * @throws SQLException + */ + public void alterTable(String columnName, String columnType) throws SQLException { + StringBuilder sb = new StringBuilder("ALTER TABLE ").append(TABLE_NAME) + .append(" ADD ") + .append(columnName) + .append(" ") + .append(columnType); + + final String query = sb.toString(); + Statement stmt = connection.createStatement(); + stmt.execute(query); + } + + /** + * Insert a new article in the articles table + * + * @param article New article to insert + * @throws SQLException + */ + public void insertArticle(Article article) throws SQLException { + StringBuilder sb = new StringBuilder("INSERT INTO ").append(TABLE_NAME) + .append("(id, title, author) ") + .append("VALUES (?,?,?)"); + + final String query = sb.toString(); + PreparedStatement preparedStatement = connection.prepareStatement(query); + preparedStatement.setString(1, article.getId().toString()); + preparedStatement.setString(2, article.getTitle()); + preparedStatement.setString(3, article.getAuthor()); + preparedStatement.execute(); + } + + /** + * Select article by Title + * + * @param title title of the article to retrieve + * @return article with the given title + * @throws SQLException + */ + public Article selectByTitle(String title) throws SQLException { + StringBuilder sb = new StringBuilder("SELECT * FROM ").append(TABLE_NAME) + .append(" WHERE title = ?"); + + final String query = sb.toString(); + PreparedStatement preparedStatement = connection.prepareStatement(query); + preparedStatement.setString(1, title); + + try (ResultSet rs = preparedStatement.executeQuery()) { + + List
articles = new ArrayList<>(); + + while (rs.next()) { + Article article = new Article( + UUID.fromString(rs.getString("id")), + rs.getString("title"), + rs.getString("author") + ); + articles.add(article); + } + return articles.get(0); + } + + } + + /** + * Select all the articles + * + * @return list of all articles + * @throws SQLException + */ + public List
selectAll() throws SQLException { + StringBuilder sb = new StringBuilder("SELECT * FROM ").append(TABLE_NAME); + + final String query = sb.toString(); + PreparedStatement preparedStatement = connection.prepareStatement(query); + try (ResultSet rs = preparedStatement.executeQuery()) { + + List
articles = new ArrayList<>(); + + while (rs.next()) { + Article article = new Article( + UUID.fromString(rs.getString("id")), + rs.getString("title"), + rs.getString("author") + ); + articles.add(article); + } + return articles; + } + } + + /** + * Delete article by title + * + * @param title title of the article to delete + * @throws SQLException + */ + public void deleteArticleByTitle(String title) throws SQLException { + StringBuilder sb = new StringBuilder("DELETE FROM ").append(TABLE_NAME) + .append(" WHERE title = ?"); + + final String query = sb.toString(); + PreparedStatement preparedStatement = connection.prepareStatement(query); + preparedStatement.setString(1, title); + preparedStatement.execute(); + } + + /** + * Delete all rows in the table + * + * @throws SQLException + */ + public void truncateTable() throws SQLException { + StringBuilder sb = new StringBuilder("TRUNCATE TABLE ").append(TABLE_NAME); + + final String query = sb.toString(); + Statement stmt = connection.createStatement(); + stmt.execute(query); + } + + /** + * Delete table + */ + public void deleteTable() throws SQLException { + StringBuilder sb = new StringBuilder("DROP TABLE IF EXISTS ").append(TABLE_NAME); + + final String query = sb.toString(); + Statement stmt = connection.createStatement(); + stmt.execute(query); + } +} diff --git a/persistence-modules/java-cockroachdb/src/test/java/com/baeldung/cockroachdb/ArticleRepositoryIntegrationTest.java b/persistence-modules/java-cockroachdb/src/test/java/com/baeldung/cockroachdb/ArticleRepositoryIntegrationTest.java new file mode 100644 index 0000000000..9eb00b3651 --- /dev/null +++ b/persistence-modules/java-cockroachdb/src/test/java/com/baeldung/cockroachdb/ArticleRepositoryIntegrationTest.java @@ -0,0 +1,208 @@ +package com.baeldung.cockroachdb; + +import com.baeldung.cockroachdb.domain.Article; +import com.baeldung.cockroachdb.repository.ArticleRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.postgresql.util.PSQLException; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class ArticleRepositoryIntegrationTest { + + private static final String TABLE_NAME = "articles"; + + private Connection con; + private ArticleRepository articleRepository; + + @Before + public void connect() throws Exception { + Class.forName("org.postgresql.Driver"); + con = DriverManager.getConnection("jdbc:postgresql://localhost:26257/testdb", "user17", "qwerty"); + + articleRepository = new ArticleRepository(con); + } + + @Test + public void whenCreatingTable_thenCreatedCorrectly() throws Exception { + articleRepository.deleteTable(); + articleRepository.createTable(); + + PreparedStatement preparedStatement = con.prepareStatement("SHOW TABLES"); + ResultSet resultSet = preparedStatement.executeQuery(); + List tables = new ArrayList<>(); + while (resultSet.next()) { + tables.add(resultSet.getString("Table")); + } + + assertTrue(tables.stream().anyMatch(t -> t.equals(TABLE_NAME))); + } + + @Test + public void whenAlteringTheTable_thenColumnAddedCorrectly() throws SQLException { + articleRepository.deleteTable(); + articleRepository.createTable(); + + String columnName = "creationdate"; + articleRepository.alterTable(columnName, "DATE"); + + String query = "SHOW COLUMNS FROM " + TABLE_NAME; + PreparedStatement preparedStatement = con.prepareStatement(query); + ResultSet resultSet = preparedStatement.executeQuery(); + List columns = new ArrayList<>(); + while (resultSet.next()) { + columns.add(resultSet.getString("Field")); + } + + assertTrue(columns.stream().anyMatch(c -> c.equals(columnName))); + } + + @Test + public void whenInsertingNewArticle_thenArticleExists() throws SQLException { + articleRepository.deleteTable(); + articleRepository.createTable(); + + String title = "Guide to CockroachDB in Java"; + String author = "baeldung"; + Article article = new Article(UUID.randomUUID(), title, author); + articleRepository.insertArticle(article); + + Article savedArticle = articleRepository.selectByTitle(title); + assertEquals(article.getTitle(), savedArticle.getTitle()); + } + + @Test + public void whenSelectingAllArticles_thenAllArticlesAreReturned() throws SQLException { + articleRepository.deleteTable(); + articleRepository.createTable(); + + Article article = new Article(UUID.randomUUID(), "Guide to CockroachDB in Java", "baeldung"); + articleRepository.insertArticle(article); + + article = new Article(UUID.randomUUID(), "A Guide to MongoDB with Java", "baeldung"); + articleRepository.insertArticle(article); + + List
savedArticles = articleRepository.selectAll(); + + assertEquals(2, savedArticles.size()); + assertTrue(savedArticles.stream().anyMatch(a -> a.getTitle().equals("Guide to CockroachDB in Java"))); + assertTrue(savedArticles.stream().anyMatch(a -> a.getTitle().equals("A Guide to MongoDB with Java"))); + } + + @Test + public void whenDeletingArticleByTtile_thenArticleIsDeleted() throws SQLException { + articleRepository.deleteTable(); + articleRepository.createTable(); + + Article article = new Article(UUID.randomUUID(), "Guide to CockroachDB in Java", "baeldung"); + articleRepository.insertArticle(article); + + article = new Article(UUID.randomUUID(), "A Guide to MongoDB with Java", "baeldung"); + articleRepository.insertArticle(article); + + articleRepository.deleteArticleByTitle("A Guide to MongoDB with Java"); + + List
savedArticles = articleRepository.selectAll(); + assertEquals(1, savedArticles.size()); + assertTrue(savedArticles.stream().anyMatch(a -> a.getTitle().equals("Guide to CockroachDB in Java"))); + assertFalse(savedArticles.stream().anyMatch(a -> a.getTitle().equals("A Guide to MongoDB with Java"))); + } + + @Test(expected = PSQLException.class) + public void whenDeletingATable_thenExceptionIfAccessed() throws SQLException { + articleRepository.createTable(); + articleRepository.deleteTable(); + + StringBuilder sb = new StringBuilder("SELECT * FROM ").append(TABLE_NAME); + + final String query = sb.toString(); + PreparedStatement preparedStatement = con.prepareStatement(query); + preparedStatement.executeQuery(); + } + + @Test + public void whenTruncatingATable_thenEmptyTable() throws SQLException { + articleRepository.deleteTable(); + articleRepository.createTable(); + + Article article = new Article(UUID.randomUUID(), "Guide to CockroachDB in Java", "baeldung"); + articleRepository.insertArticle(article); + + article = new Article(UUID.randomUUID(), "A Guide to MongoDB with Java", "baeldung"); + articleRepository.insertArticle(article); + + articleRepository.truncateTable(); + + List
savedArticles = articleRepository.selectAll(); + assertEquals(0, savedArticles.size()); + } + + @Test + public void whenInsertingTwoArticlesWithSamePrimaryKeyInASingleTransaction_thenRollback() throws SQLException { + articleRepository.deleteTable(); + articleRepository.createTable(); + + try { + con.setAutoCommit(false); + + UUID articleId = UUID.randomUUID(); + + Article article = new Article(articleId, "Guide to CockroachDB in Java", "baeldung"); + articleRepository.insertArticle(article); + + article = new Article(articleId, "A Guide to MongoDB with Java", "baeldung"); + articleRepository.insertArticle(article); + + con.commit(); + } catch (Exception e) { + con.rollback(); + } finally { + con.setAutoCommit(true); + } + + List
savedArticles = articleRepository.selectAll(); + assertEquals(0, savedArticles.size()); + } + + @Test + public void whenInsertingTwoArticlesInASingleTransaction_thenInserted() throws SQLException { + articleRepository.deleteTable(); + articleRepository.createTable(); + + try { + con.setAutoCommit(false); + + Article article = new Article(UUID.randomUUID(), "Guide to CockroachDB in Java", "baeldung"); + articleRepository.insertArticle(article); + + article = new Article(UUID.randomUUID(), "A Guide to MongoDB with Java", "baeldung"); + articleRepository.insertArticle(article); + + con.commit(); + } catch (Exception e) { + con.rollback(); + } finally { + con.setAutoCommit(true); + } + + List
savedArticles = articleRepository.selectAll(); + assertEquals(2, savedArticles.size()); + assertTrue(savedArticles.stream().anyMatch(a -> a.getTitle().equals("Guide to CockroachDB in Java"))); + assertTrue(savedArticles.stream().anyMatch(a -> a.getTitle().equals("A Guide to MongoDB with Java"))); + } + + @After + public void disconnect() throws SQLException { + articleRepository = null; + con.close(); + con = null; + } +} diff --git a/persistence-modules/spring-hibernate-5/pom.xml b/persistence-modules/spring-hibernate-5/pom.xml index 88db38b2fc..86e952c0e4 100644 --- a/persistence-modules/spring-hibernate-5/pom.xml +++ b/persistence-modules/spring-hibernate-5/pom.xml @@ -179,7 +179,7 @@ - 4.3.10.RELEASE + 5.0.2.RELEASE 1.10.6.RELEASE diff --git a/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/manytomany/spring/PersistenceConfig.java b/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/manytomany/spring/PersistenceConfig.java index 6f359054b6..5dace1f742 100644 --- a/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/manytomany/spring/PersistenceConfig.java +++ b/persistence-modules/spring-hibernate-5/src/main/java/com/baeldung/manytomany/spring/PersistenceConfig.java @@ -10,8 +10,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; -import org.springframework.orm.hibernate4.HibernateTransactionManager; -import org.springframework.orm.hibernate4.LocalSessionFactoryBean; +import org.springframework.orm.hibernate5.HibernateTransactionManager; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; diff --git a/pom.xml b/pom.xml index 38fa010f95..1050bb8ba2 100644 --- a/pom.xml +++ b/pom.xml @@ -86,6 +86,7 @@ jackson vavr + java-lite javax-servlets javaxval jaxb @@ -268,6 +269,7 @@ deeplearning4j lucene vraptor + persistence-modules/java-cockroachdb diff --git a/spring-custom-aop/spring-custom-aop/pom.xml b/spring-custom-aop/spring-custom-aop/pom.xml index 7e9da03b54..0bab7a4057 100644 --- a/spring-custom-aop/spring-custom-aop/pom.xml +++ b/spring-custom-aop/spring-custom-aop/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung - spring-boot + spring-custom-aop 0.0.1-SNAPSHOT war spring-boot diff --git a/spring-custom-aop/spring-custom-aop/src/main/java/org/baeldung/endpoints/EndpointDTO.java b/spring-custom-aop/spring-custom-aop/src/main/java/org/baeldung/endpoints/EndpointDTO.java new file mode 100644 index 0000000000..d12d6419e1 --- /dev/null +++ b/spring-custom-aop/spring-custom-aop/src/main/java/org/baeldung/endpoints/EndpointDTO.java @@ -0,0 +1,39 @@ +package org.baeldung.endpoints; + +public class EndpointDTO { + private String id; + private boolean enabled; + private boolean sensitive; + + public EndpointDTO(String id, boolean enabled, boolean sensitive) { + super(); + this.id = id; + this.enabled = enabled; + this.sensitive = sensitive; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean isSensitive() { + return sensitive; + } + + public void setSensitive(boolean sensitive) { + this.sensitive = sensitive; + } + +} diff --git a/spring-custom-aop/spring-custom-aop/src/main/java/org/baeldung/endpoints/ListEndpoints.java b/spring-custom-aop/spring-custom-aop/src/main/java/org/baeldung/endpoints/ListEndpoints.java index 0add741a1f..f434351a51 100644 --- a/spring-custom-aop/spring-custom-aop/src/main/java/org/baeldung/endpoints/ListEndpoints.java +++ b/spring-custom-aop/spring-custom-aop/src/main/java/org/baeldung/endpoints/ListEndpoints.java @@ -1,6 +1,7 @@ package org.baeldung.endpoints; import java.util.List; +import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.endpoint.AbstractEndpoint; @@ -8,16 +9,16 @@ import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.stereotype.Component; @Component -public class ListEndpoints extends AbstractEndpoint> { - private List endpoints; +public class ListEndpoints extends AbstractEndpoint> { + private List endpointDTOs; @Autowired public ListEndpoints(List endpoints) { super("listEndpoints"); - this.endpoints = endpoints; + this.endpointDTOs = endpoints.stream().map(endpoint -> new EndpointDTO(endpoint.getId(), endpoint.isEnabled(), endpoint.isSensitive())).collect(Collectors.toList()); } - public List invoke() { - return this.endpoints; + public List invoke() { + return this.endpointDTOs; } } \ No newline at end of file diff --git a/spring-jenkins-pipeline/README.md b/spring-jenkins-pipeline/README.md index 7e562664e6..8c10e85da2 100644 --- a/spring-jenkins-pipeline/README.md +++ b/spring-jenkins-pipeline/README.md @@ -10,7 +10,6 @@ This is the code of a simple API for some CRUD operations build using Spring Boo - MongoDB ### Running - To build and start the server simply type ```bash @@ -20,4 +19,8 @@ $ mvn spring-boot:run -Dserver.port=8989 Now with default configurations it will be available at: [http://localhost:8080](http://localhost:8080) -Enjoy it :) \ No newline at end of file +Enjoy it :) + +### Relevant articles + +- [Intro to Jenkins 2 and the Power of Pipelines](http://www.baeldung.com/jenkins-pipelines) diff --git a/vavr/src/main/java/com/baeldung/vavr/future/Util.java b/vavr/src/main/java/com/baeldung/vavr/future/Util.java deleted file mode 100644 index 790ef2bf88..0000000000 --- a/vavr/src/main/java/com/baeldung/vavr/future/Util.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung.vavr.future; - -public class Util { - - public static String appendData(String initial) { - return initial + "Baeldung!"; - } - - public static int divideByZero(int num) { - return num / 0; - } - - public static String getSubstringMinusOne(String s) { - return s.substring(-1); - } - - public static String getSubstringMinusTwo(String s) { - return s.substring(-2); - } -} diff --git a/vavr/src/test/java/com/baeldung/vavr/future/FutureTest.java b/vavr/src/test/java/com/baeldung/vavr/future/FutureTest.java index dd678bcad0..002919a937 100644 --- a/vavr/src/test/java/com/baeldung/vavr/future/FutureTest.java +++ b/vavr/src/test/java/com/baeldung/vavr/future/FutureTest.java @@ -1,119 +1,102 @@ package com.baeldung.vavr.future; -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; - -import org.junit.Test; - import io.vavr.Tuple; -import io.vavr.Tuple2; import io.vavr.concurrent.Future; import io.vavr.control.Option; import io.vavr.control.Try; +import org.junit.Test; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import static java.util.concurrent.Executors.newSingleThreadExecutor; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; public class FutureTest { - + private static final String error = "Failed to get underlying value."; + private static final String HELLO = "Welcome to Baeldung!"; @Test - public void whenChangeExecutorService_thenCorrect() throws InterruptedException { - String initialValue = "Welcome to "; - Future resultFuture = Future.of( - Executors.newSingleThreadExecutor(), - () -> Util.appendData(initialValue)); - Thread.sleep(20); - String result = resultFuture.getOrElse(error); + public void whenChangeExecutorService_thenCorrect() { + String result = Future.of(newSingleThreadExecutor(), () -> HELLO) + .getOrElse(error); - assertThat(result).isEqualTo("Welcome to Baeldung!"); + assertThat(result) + .isEqualTo(HELLO); } @Test - public void whenAppendData_thenCorrect1() throws InterruptedException { - String initialValue = "Welcome to "; - Future resultFuture = Future.of(() -> Util.appendData(initialValue)); - Thread.sleep(20); - String result = resultFuture.getOrElse(new String(error)); + public void whenAppendData_thenCorrect1() { + String result = Future.of(() -> HELLO) + .getOrElse(error); - assertThat(result).isEqualTo("Welcome to Baeldung!"); + assertThat(result) + .isEqualTo(HELLO); } @Test - public void whenAppendData_thenCorrect2() throws InterruptedException { - String initialValue = "Welcome to "; - Future resultFuture = Future.of(() -> Util.appendData(initialValue)); - Thread.sleep(20); - resultFuture.await(); + public void whenAppendData_thenCorrect2() { + Future resultFuture = Future.of(() -> HELLO) + .await(); + Option> futureOption = resultFuture.getValue(); - Try futureTry = futureOption.get(); - String result = futureTry.getOrElse(error); + String result = futureOption.get().getOrElse(error); - assertThat(result).isEqualTo("Welcome to Baeldung!"); + assertThat(result) + .isEqualTo(HELLO); } @Test - public void whenAppendData_thenSuccess() throws InterruptedException { - String initialValue = "Welcome to "; - Future resultFuture = Future.of(() -> Util.appendData(initialValue)) + public void whenAppendData_thenSuccess() { + String result = Future.of(() -> HELLO) .onSuccess(finalResult -> System.out.println("Successfully Completed - Result: " + finalResult)) - .onFailure(finalResult -> System.out.println("Failed - Result: " + finalResult)); - Thread.sleep(20); - String result = resultFuture.getOrElse(error); + .onFailure(finalResult -> System.out.println("Failed - Result: " + finalResult)) + .getOrElse(error); - assertThat(result).isEqualTo("Welcome to Baeldung!"); + assertThat(result) + .isEqualTo(HELLO); } @Test - public void whenChainingCallbacks_thenCorrect() throws InterruptedException { - String initialValue = "Welcome to "; - Future resultFuture = Future.of(() -> Util.appendData(initialValue)) - .andThen(finalResult -> System.out.println("Completed - 1: " + finalResult)) - .andThen(finalResult -> System.out.println("Completed - 2: " + finalResult)); - Thread.sleep(20); - String result = resultFuture.getOrElse(error); - - assertThat(result).isEqualTo("Welcome to Baeldung!"); + public void whenChainingCallbacks_thenCorrect() { + Future.of(() -> HELLO) + .andThen(r -> System.out.println("Completed - 1: " + r)) + .andThen(r -> System.out.println("Completed - 2: " + r)); } @Test - public void whenCallAwait_thenCorrect() throws InterruptedException { - String initialValue = "Welcome to "; - Future resultFuture = Future.of(() -> Util.appendData(initialValue)); - Thread.sleep(20); - resultFuture = resultFuture.await(); - String result = resultFuture.getOrElse(error); + public void whenCallAwait_thenCorrect() { + Future resultFuture = Future.of(() -> HELLO) + .await(); + String result = resultFuture.getValue().get().getOrElse(error); - assertThat(result).isEqualTo("Welcome to Baeldung!"); + assertThat(result) + .isEqualTo(HELLO); } @Test - public void whenDivideByZero_thenGetThrowable1() throws InterruptedException { - Future resultFuture = Future.of(() -> Util.divideByZero(10)); - Thread.sleep(20); - Future throwableFuture = resultFuture.failed(); - Throwable throwable = throwableFuture.getOrElse(new Throwable()); + public void whenDivideByZero_thenGetThrowable1() { + Future resultFuture = Future.of(() -> 10 / 0); - assertThat(throwable.getMessage()).isEqualTo("/ by zero"); + assertThatThrownBy(resultFuture::get) + .isInstanceOf(ArithmeticException.class); } @Test - public void whenDivideByZero_thenGetThrowable2() throws InterruptedException { - Future resultFuture = Future.of(() -> Util.divideByZero(10)); - Thread.sleep(20); - resultFuture.await(); - Option throwableOption = resultFuture.getCause(); - Throwable throwable = throwableOption.getOrElse(new Throwable()); + public void whenDivideByZero_thenGetThrowable2() { + Future resultFuture = Future.of(() -> 10 / 0) + .await(); - assertThat(throwable.getMessage()).isEqualTo("/ by zero"); + assertThat(resultFuture.getCause().get().getMessage()) + .isEqualTo("/ by zero"); } @Test - public void whenDivideByZero_thenCorrect() throws InterruptedException { - Future resultFuture = Future.of(() -> Util.divideByZero(10)); - Thread.sleep(20); - resultFuture.await(); + public void whenDivideByZero_thenCorrect() { + Future resultFuture = Future.of(() -> 10 / 0) + .await(); assertThat(resultFuture.isCompleted()).isTrue(); assertThat(resultFuture.isSuccess()).isFalse(); @@ -121,76 +104,70 @@ public class FutureTest { } @Test - public void whenAppendData_thenFutureNotEmpty() throws InterruptedException { - String initialValue = "Welcome to "; - Future resultFuture = Future.of(() -> Util.appendData(initialValue)); - Thread.sleep(20); - resultFuture.await(); + public void whenAppendData_thenFutureNotEmpty() { + Future resultFuture = Future.of(() -> HELLO) + .await(); - assertThat(resultFuture.isEmpty()).isFalse(); + assertThat(resultFuture.isEmpty()) + .isFalse(); } @Test - public void whenCallZip_thenCorrect() throws InterruptedException { - Future> future = Future.of(() -> "John") - .zip(Future.of(() -> new Integer(5))); - Thread.sleep(20); - future.await(); + public void whenCallZip_thenCorrect() { + Future f1 = Future.of(() -> "hello1"); + Future f2 = Future.of(() -> "hello2"); - assertThat(future.getOrElse(new Tuple2(error, 0))) - .isEqualTo(Tuple.of("John", new Integer(5))); + assertThat(f1.zip(f2).get()) + .isEqualTo(Tuple.of("hello1", "hello2")); } @Test public void whenConvertToCompletableFuture_thenCorrect() throws InterruptedException, ExecutionException { - String initialValue = "Welcome to "; - Future resultFuture = Future.of(() -> Util.appendData(initialValue)); - Thread.sleep(20); - CompletableFuture convertedFuture = resultFuture.toCompletableFuture(); + CompletableFuture convertedFuture = Future.of(() -> HELLO) + .toCompletableFuture(); - assertThat(convertedFuture.get()).isEqualTo("Welcome to Baeldung!"); + assertThat(convertedFuture.get()) + .isEqualTo(HELLO); } @Test - public void whenCallMap_thenCorrect() throws InterruptedException { - Future futureResult = Future.of(() -> new StringBuilder("from Baeldung")) - .map(a -> "Hello " + a); - Thread.sleep(20); - futureResult.await(); + public void whenCallMap_thenCorrect() { + Future futureResult = Future.of(() -> "from Baeldung") + .map(a -> "Hello " + a) + .await(); - assertThat(futureResult.getOrElse(error)).isEqualTo("Hello from Baeldung"); + assertThat(futureResult.get()) + .isEqualTo("Hello from Baeldung"); } @Test - public void whenFutureFails_thenGetErrorMessage() throws InterruptedException { - Future resultFuture = Future.of(() -> Util.getSubstringMinusOne("Hello")); - Thread.sleep(20); - Future errorMessageFuture = resultFuture.recover(Throwable::getMessage); - String errorMessage = errorMessageFuture.getOrElse(error); + public void whenFutureFails_thenGetErrorMessage() { + Future future = Future.of(() -> "Hello".substring(-1)) + .recover(x -> "fallback value"); - assertThat(errorMessage).isEqualTo("String index out of range: -1"); + assertThat(future.get()) + .isEqualTo("fallback value"); } @Test - public void whenFutureFails_thenGetAnotherFuture() throws InterruptedException { - Future resultFuture = Future.of(() -> Util.getSubstringMinusOne("Hello")); - Thread.sleep(20); - Future errorMessageFuture = resultFuture.recoverWith(a -> Future.of(a::getMessage)); - String errorMessage = errorMessageFuture.getOrElse(error); + public void whenFutureFails_thenGetAnotherFuture() { + Future future = Future.of(() -> "Hello".substring(-1)) + .recoverWith(x -> Future.of(() -> "fallback value")); - assertThat(errorMessage).isEqualTo("String index out of range: -1"); + assertThat(future.get()) + .isEqualTo("fallback value"); } @Test - public void whenBothFuturesFail_thenGetErrorMessage() throws InterruptedException { - Future future1 = Future.of(() -> Util.getSubstringMinusOne("Hello")); - Future future2 = Future.of(() -> Util.getSubstringMinusTwo("Hello")); - Thread.sleep(20); - Future errorMessageFuture = future1.fallbackTo(future2); + public void whenBothFuturesFail_thenGetErrorMessage() { + Future f1 = Future.of(() -> "Hello".substring(-1)); + Future f2 = Future.of(() -> "Hello".substring(-2)); + + Future errorMessageFuture = f1.fallbackTo(f2); Future errorMessage = errorMessageFuture.failed(); - + assertThat( - errorMessage.getOrElse(new Throwable()).getMessage()) + errorMessage.get().getMessage()) .isEqualTo("String index out of range: -1"); } }