Merge remote-tracking branch 'eugenp/master'

This commit is contained in:
DOHA 2018-01-07 13:49:34 +02:00
commit da77f09e88
44 changed files with 1330 additions and 153 deletions

View File

@ -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

View File

@ -39,6 +39,12 @@
<artifactId>jgrapht-core</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.9.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -1,4 +1,4 @@
package com.baeldung.streamApi;
package com.baeldung.stream;
import java.util.List;
import java.util.stream.Stream;

View File

@ -16,7 +16,7 @@ public class StreamApi {
}
public static String getLastElementUsingSkip(List<String> valueList) {
long count = valueList.stream().count();
long count = (long) valueList.size();
Stream<String> stream = valueList.stream();
return stream.skip(count - 1).findFirst().orElse(null);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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)

View File

@ -389,6 +389,16 @@
</arguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>

View File

@ -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;
}
}

View File

@ -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;
/**
* <p>This is a simple description of the method. . .
* <a href="http://www.supermanisthegreatest.com">Superman!</a>
* </p>
* @param incomingDamage the amount of incoming damage
* @return the amount of health hero has after attack
* @see <a href="http://www.link_to_jira/HERO-402">HERO-402</a>
* @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;
}
}

View File

@ -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();

View File

@ -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();
}
}

View File

@ -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<Callable<Integer>> randomCallables = new ArrayList<>();
List<Callable<Integer>> 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();
}
}

View File

@ -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)

2
java-lite/README.md Normal file
View File

@ -0,0 +1,2 @@
### Relevant Articles:
- [RESTFul CRUD application with JavaLite] ()

105
java-lite/pom.xml Normal file
View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.baeldung</groupId>
<artifactId>java-lite</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<properties>
<jetty.maven.plugin.version>9.3.4.RC1</jetty.maven.plugin.version>
<activejdbc.version>1.4.13</activejdbc.version>
<activeweb.version>1.15</activeweb.version>
<mysql.connector.java.version>5.1.45</mysql.connector.java.version>
<sun.tools.version>1.7.0</sun.tools.version>
<jackson.version>1.8.2</jackson.version>
<junit.version>4.11</junit.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty.maven.plugin.version}</version>
<configuration>
<systemProperties>
<systemProperty>
<name>activejdbc.log</name>
<value></value>
</systemProperty>
<systemProperty>
<name>active_reload</name>
<value>true</value>
</systemProperty>
<systemProperty>
<name>activeweb.log.request</name>
<value>true</value>
</systemProperty>
</systemProperties>
</configuration>
</plugin>
<plugin>
<groupId>org.javalite</groupId>
<artifactId>activejdbc-instrumentation</artifactId>
<version>${activejdbc.version}</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>instrument</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.javalite</groupId>
<artifactId>activeweb</artifactId>
<version>${activeweb.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.java.version}</version>
</dependency>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>${sun.tools.version}</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-lgpl</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-lgpl</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -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) {
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,7 @@
package app.models;
import org.javalite.activejdbc.Model;
public class Product extends Model {
}

View File

@ -0,0 +1,4 @@
development.driver=com.mysql.jdbc.Driver
development.username=user
development.password=password
development.url=jdbc:mysql://localhost/dbname

View File

@ -0,0 +1 @@
,

View File

@ -0,0 +1,4 @@
{
"id" : ${product.id},
"name" : "${product.name}"
}

View File

@ -0,0 +1 @@
[<@render partial="product" collection=products spacer="comma"/>]

View File

@ -0,0 +1,4 @@
{
"message" : "${message}",
"code" : ${code}
}

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<filter>
<filter-name>dispatcher</filter-name>
<filter-class>org.javalite.activeweb.RequestDispatcher</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>css,images,js,ico</param-value>
</init-param>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>dispatcher</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

View File

@ -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"));
}
}

View File

@ -0,0 +1,2 @@
### Relevant Articles:
- [Guide to CockroachDB in Java](http://www.baeldung.com/)

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent-modules</artifactId>
<groupId>com.baeldung</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>java-cockroachdb</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<postgresql.version>42.1.4</postgresql.version>
</properties>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*ManualTest.java</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<repositories>
<repository>
<id>Central</id>
<name>Central</name>
<url>http://repo1.maven.org/maven2/</url>
<layout>default</layout>
</repository>
</repositories>
</project>

View File

@ -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;
}
}

View File

@ -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<Article> 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<Article> 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<Article> 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);
}
}

View File

@ -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<String> 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<String> 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<Article> 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<Article> 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<Article> 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<Article> 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<Article> 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;
}
}

View File

@ -179,7 +179,7 @@
<properties>
<!-- Spring -->
<org.springframework.version>4.3.10.RELEASE</org.springframework.version>
<org.springframework.version>5.0.2.RELEASE</org.springframework.version>
<org.springframework.data.version>1.10.6.RELEASE</org.springframework.data.version>

View File

@ -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;

View File

@ -86,6 +86,7 @@
<module>jackson</module>
<!-- <module>persistence-modules/java-cassandra</module> -->
<module>vavr</module>
<module>java-lite</module>
<module>javax-servlets</module>
<module>javaxval</module>
<module>jaxb</module>
@ -268,6 +269,7 @@
<module>deeplearning4j</module>
<module>lucene</module>
<module>vraptor</module>
<module>persistence-modules/java-cockroachdb</module>
</modules>
<dependencies>

View File

@ -2,7 +2,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>spring-boot</artifactId>
<artifactId>spring-custom-aop</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>spring-boot</name>

View File

@ -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;
}
}

View File

@ -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<List<Endpoint>> {
private List<Endpoint> endpoints;
public class ListEndpoints extends AbstractEndpoint<List<EndpointDTO>> {
private List<EndpointDTO> endpointDTOs;
@Autowired
public ListEndpoints(List<Endpoint> 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<Endpoint> invoke() {
return this.endpoints;
public List<EndpointDTO> invoke() {
return this.endpointDTOs;
}
}

View File

@ -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 :)
Enjoy it :)
### Relevant articles
- [Intro to Jenkins 2 and the Power of Pipelines](http://www.baeldung.com/jenkins-pipelines)

View File

@ -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);
}
}

View File

@ -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<String> 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<String> 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<String> resultFuture = Future.of(() -> Util.appendData(initialValue));
Thread.sleep(20);
resultFuture.await();
public void whenAppendData_thenCorrect2() {
Future<String> resultFuture = Future.of(() -> HELLO)
.await();
Option<Try<String>> futureOption = resultFuture.getValue();
Try<String> 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<String> 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<String> 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<String> resultFuture = Future.of(() -> Util.appendData(initialValue));
Thread.sleep(20);
resultFuture = resultFuture.await();
String result = resultFuture.getOrElse(error);
public void whenCallAwait_thenCorrect() {
Future<String> 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<Integer> resultFuture = Future.of(() -> Util.divideByZero(10));
Thread.sleep(20);
Future<Throwable> throwableFuture = resultFuture.failed();
Throwable throwable = throwableFuture.getOrElse(new Throwable());
public void whenDivideByZero_thenGetThrowable1() {
Future<Integer> 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<Integer> resultFuture = Future.of(() -> Util.divideByZero(10));
Thread.sleep(20);
resultFuture.await();
Option<Throwable> throwableOption = resultFuture.getCause();
Throwable throwable = throwableOption.getOrElse(new Throwable());
public void whenDivideByZero_thenGetThrowable2() {
Future<Integer> 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<Integer> resultFuture = Future.of(() -> Util.divideByZero(10));
Thread.sleep(20);
resultFuture.await();
public void whenDivideByZero_thenCorrect() {
Future<Integer> 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<String> resultFuture = Future.of(() -> Util.appendData(initialValue));
Thread.sleep(20);
resultFuture.await();
public void whenAppendData_thenFutureNotEmpty() {
Future<String> resultFuture = Future.of(() -> HELLO)
.await();
assertThat(resultFuture.isEmpty()).isFalse();
assertThat(resultFuture.isEmpty())
.isFalse();
}
@Test
public void whenCallZip_thenCorrect() throws InterruptedException {
Future<Tuple2<String, Integer>> future = Future.of(() -> "John")
.zip(Future.of(() -> new Integer(5)));
Thread.sleep(20);
future.await();
public void whenCallZip_thenCorrect() {
Future<String> f1 = Future.of(() -> "hello1");
Future<String> f2 = Future.of(() -> "hello2");
assertThat(future.getOrElse(new Tuple2<String, Integer>(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<String> resultFuture = Future.of(() -> Util.appendData(initialValue));
Thread.sleep(20);
CompletableFuture<String> convertedFuture = resultFuture.toCompletableFuture();
CompletableFuture<String> 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<String> futureResult = Future.of(() -> new StringBuilder("from Baeldung"))
.map(a -> "Hello " + a);
Thread.sleep(20);
futureResult.await();
public void whenCallMap_thenCorrect() {
Future<String> 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<String> resultFuture = Future.of(() -> Util.getSubstringMinusOne("Hello"));
Thread.sleep(20);
Future<String> errorMessageFuture = resultFuture.recover(Throwable::getMessage);
String errorMessage = errorMessageFuture.getOrElse(error);
public void whenFutureFails_thenGetErrorMessage() {
Future<String> 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<String> resultFuture = Future.of(() -> Util.getSubstringMinusOne("Hello"));
Thread.sleep(20);
Future<String> errorMessageFuture = resultFuture.recoverWith(a -> Future.of(a::getMessage));
String errorMessage = errorMessageFuture.getOrElse(error);
public void whenFutureFails_thenGetAnotherFuture() {
Future<String> 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<String> future1 = Future.of(() -> Util.getSubstringMinusOne("Hello"));
Future<String> future2 = Future.of(() -> Util.getSubstringMinusTwo("Hello"));
Thread.sleep(20);
Future<String> errorMessageFuture = future1.fallbackTo(future2);
public void whenBothFuturesFail_thenGetErrorMessage() {
Future<String> f1 = Future.of(() -> "Hello".substring(-1));
Future<String> f2 = Future.of(() -> "Hello".substring(-2));
Future<String> errorMessageFuture = f1.fallbackTo(f2);
Future<Throwable> errorMessage = errorMessageFuture.failed();
assertThat(
errorMessage.getOrElse(new Throwable()).getMessage())
errorMessage.get().getMessage())
.isEqualTo("String index out of range: -1");
}
}