Merge remote-tracking branch 'upstream/master' into JAVA-3570

This commit is contained in:
Krzysztof Woyke 2020-12-22 10:50:48 +01:00
commit 515d213c90
147 changed files with 2111 additions and 24 deletions

View File

@ -0,0 +1,26 @@
package com.baeldung.java14.newfeatues;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class MultilineUnitTest {
@SuppressWarnings("preview")
String multiline = """
A quick brown fox jumps over a lazy dog; \
the lazy dog howls loudly.""";
@SuppressWarnings("preview")
String anotherMultiline = """
A quick brown fox jumps over a lazy dog;
the lazy dog howls loudly.""";
@Test
public void givenMultilineString_whenSlashUsed_thenNoNewLine() {
assertFalse(multiline.contains("\n"));
assertTrue(anotherMultiline.contains("\n"));
}
}

View File

@ -0,0 +1,38 @@
package com.baeldung.java14.newfeatues;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class RecordUnitTest {
@SuppressWarnings("preview")
public record User(int id, String password) {
};
private User user1 = new User(0, "UserOne");
@Test
public void givenRecord_whenObjInitialized_thenValuesCanBeFetchedWithGetters() {
assertEquals(0, user1.id());
assertEquals("UserOne", user1.password());
}
@Test
public void whenRecord_thenEqualsImplemented() {
User user2 = user1;
assertEquals(user1, user2);
}
@Test
public void whenRecord_thenToStringImplemented() {
assertTrue(user1.toString()
.contains("UserOne"));
}
}

View File

@ -0,0 +1,50 @@
package com.baeldung.java14.newfeatues;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class SwitchExprUnitTest {
@Test
public void givenDay_whenSunday_thenWeekend() {
assertTrue(isTodayHolidayInJava8("SUNDAY"));
assertTrue(isTodayHolidayInJava14("SUNDAY"));
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> isTodayHolidayInJava8("SOMEDAY"));
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> isTodayHolidayInJava14("SOMEDAY"));
}
private boolean isTodayHolidayInJava8(String day) {
boolean isTodayHoliday;
switch (day) {
case "MONDAY":
case "TUESDAY":
case "WEDNESDAY":
case "THURSDAY":
case "FRIDAY":
isTodayHoliday = false;
break;
case "SATURDAY":
case "SUNDAY":
isTodayHoliday = true;
break;
default:
throw new IllegalArgumentException("What's a " + day);
}
return isTodayHoliday;
}
private boolean isTodayHolidayInJava14(String day) {
return switch (day) {
case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> false;
case "SATURDAY", "SUNDAY" -> true;
default -> throw new IllegalArgumentException("What's a " + day);
};
}
}

View File

@ -0,0 +1,7 @@
=========
## Core Java Collections Cookbooks and Examples
### Relevant Articles:
- [ArrayList vs. LinkedList vs. HashMap in Java](https://www.baeldung.com/java-arraylist-vs-linkedlist-vs-hashmap)

View File

@ -0,0 +1,31 @@
<?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>
<artifactId>core-java-collections-4</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-collections-4</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<assertj.version>3.18.0</assertj.version>
</properties>
</project>

View File

@ -0,0 +1,30 @@
package com.baeldung.collections.comparation;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class ArrayListUnitTest {
@Test
void givenArrayList_whenItemAddedToSpecificIndex_thenItCanBeRetrieved() {
List<String> list = new ArrayList<>();
list.add("Daniel");
list.add(0, "Marko");
assertThat(list).hasSize(2);
assertThat(list.get(0)).isEqualTo("Marko");
}
@Test
void givenArrayList_whenItemRemovedViaIndex_thenListSizeIsReduced() {
List<String> list = new ArrayList<>(Arrays.asList("Daniel", "Marko"));
list.remove(1);
assertThat(list).hasSize(1);
assertThat(list).doesNotContain("Marko");
}
}

View File

@ -0,0 +1,31 @@
package com.baeldung.collections.comparation;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
public class HashMapUnitTest {
@Test
void givenHashMap_whenItemAddedByKey_thenItCanBeRetrieved() {
Map<String, String> map = new HashMap<>();
map.put("123456", "Daniel");
map.put("654321", "Marko");
assertThat(map.get("654321")).isEqualTo("Marko");
}
@Test
void givenHashMap_whenItemRemovedByKey_thenMapSizeIsReduced() {
Map<String, String> map = new HashMap<>();
map.put("123456", "Daniel");
map.put("654321", "Marko");
map.remove("654321");
assertThat(map).hasSize(1);
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.collections.comparation;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class LinkedListUnitTest {
@Test
void givenLinkedList_whenItemIsAppended_thenItCanBeRetrieved() {
LinkedList<String> list = new LinkedList<>();
list.addLast("Daniel");
list.addFirst("Marko");
assertThat(list).hasSize(2);
assertThat(list.getLast()).isEqualTo("Daniel");
}
@Test
void givenLinkedList_whenItemIsRemoved_thenListSizeIsReduced() {
LinkedList<String> list = new LinkedList<>(Arrays.asList("Daniel", "Marko", "David"));
list.removeFirst();
list.removeLast();
assertThat(list).hasSize(1);
assertThat(list).containsExactly("Marko");
}
@Test
void givenLinkedList_whenItemInserted_thenItCanBeRetrievedAndDeleted() {
LinkedList<String> list = new LinkedList<>();
list.push("Daniel");
list.push("Marko");
assertThat(list.poll()).isEqualTo("Marko");
assertThat(list).hasSize(1);
}
}

View File

@ -0,0 +1,32 @@
package com.baeldung.collections.comparation;
import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.Test;
import java.util.*;
class ListVsMapUnitTest {
@Test
void givenList_whenIteratingTroughValues_thenEachValueIsPresent() {
List<String> list = new ArrayList<>();
list.add("Daniel");
list.add("Marko");
for (String name : list) {
assertThat(name).isIn(list);
}
assertThat(list).containsExactly("Daniel", "Marko");
}
@Test
void givenMap_whenIteratingTroughValues_thenEachValueIsPresent() {
Map<Integer, String> map = new HashMap<>();
map.put(1, "Daniel");
map.put(2, "Marko");
for (String name : map.values()) {
assertThat(name).isIn(map.values());
}
assertThat(map.values()).containsExactlyInAnyOrder("Daniel", "Marko");
}
}

View File

@ -13,4 +13,5 @@ This module contains articles about core Java input and output (IO)
- [Reading a Line at a Given Line Number From a File in Java](https://www.baeldung.com/java-read-line-at-number)
- [Find the Last Modified File in a Directory with Java](https://www.baeldung.com/java-last-modified-file)
- [Get a Filename Without the Extension in Java](https://www.baeldung.com/java-filename-without-extension)
- [Writing byte[] to a File in Java](https://www.baeldung.com/java-write-byte-array-file)
- [[<-- Prev]](/core-java-modules/core-java-io-2)

View File

@ -0,0 +1,77 @@
package com.baeldung.writebytearray;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import org.apache.commons.io.FileUtils;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import com.google.common.io.ByteSink;
import com.google.common.io.MoreFiles;
public class WriteByteArrayUnitTest {
private static byte[] dataForWriting;
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
@BeforeClass
public static void setup() throws IOException {
dataForWriting = Files.readAllBytes(Paths.get("src/test/resources/example-image.jpg"));
}
@Test
public void whenUsingFileOutputStream_thenByteArrayIsWritten() throws IOException {
File outputFile = tempFolder.newFile("example-fos.jpg");
try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
outputStream.write(dataForWriting);
assertThat(outputFile).hasBinaryContent(dataForWriting);
}
}
@Test
public void whenUsingNioFiles_thenByteArrayIsWritten() throws IOException {
File outputFile = tempFolder.newFile("example-nio-files.jpg");
Files.write(outputFile.toPath(), dataForWriting);
assertThat(outputFile).hasBinaryContent(dataForWriting);
}
@Test
public void whenUsingGuavaFiles_thenByteArrayIsWritten() throws IOException {
File outputFile = tempFolder.newFile("example-guava-files.jpg");
com.google.common.io.Files.write(dataForWriting, outputFile);
assertThat(outputFile).hasBinaryContent(dataForWriting);
}
@Test
public void whenUsingGuavaByteSink_thenByteArrayIsWritten() throws IOException {
File outputFile = tempFolder.newFile("example-guava-bs.jpg");
ByteSink byteSink = com.google.common.io.Files.asByteSink(outputFile);
byteSink.write(dataForWriting);
assertThat(outputFile).hasBinaryContent(dataForWriting);
}
@Test
public void whenUsingGuavaByteSinkMoreFiles_thenByteArrayIsWritten() throws IOException {
File outputFile = tempFolder.newFile("example-guava-bs.jpg");
ByteSink byteSink = MoreFiles.asByteSink(outputFile.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
byteSink.write(dataForWriting);
assertThat(outputFile).hasBinaryContent(dataForWriting);
}
@Test
public void whenUsingCommonsIo_thenByteArrayIsWritten() throws IOException {
File outputFile = tempFolder.newFile("example-file-utils.jpg");
FileUtils.writeByteArrayToFile(outputFile, dataForWriting);
assertThat(outputFile).hasBinaryContent(dataForWriting);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -14,4 +14,5 @@ This module contains articles about core Java Security
- [Get a List of Trusted Certificates in Java](https://www.baeldung.com/java-list-trusted-certificates)
- [Security Context Basics: User, Subject and Principal](https://www.baeldung.com/security-context-basics)
- [Java AES Encryption and Decryption](https://www.baeldung.com/java-aes-encryption-decryption)
- [InvalidAlgorithmParameterException: Wrong IV Length](https://www.baeldung.com/java-invalidalgorithmparameter-exception)
- More articles: [[<-- prev]](/core-java-modules/core-java-security)

View File

@ -34,6 +34,7 @@
<module>core-java-collections</module>
<module>core-java-collections-2</module>
<module>core-java-collections-3</module>
<module>core-java-collections-4</module>
<module>core-java-collections-array-list</module>
<module>core-java-collections-list</module>
<module>core-java-collections-list-2</module>

View File

@ -0,0 +1,28 @@
package com.baeldung.map.bytearrays;
import java.util.Arrays;
public final class BytesKey {
private final byte[] array;
public BytesKey(byte[] array) {
this.array = array;
}
public byte[] getArray() {
return array.clone();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BytesKey bytesKey = (BytesKey) o;
return Arrays.equals(array, bytesKey.array);
}
@Override
public int hashCode() {
return Arrays.hashCode(array);
}
}

View File

@ -0,0 +1,104 @@
package com.baeldung.map.bytearrays;
import com.google.common.collect.ImmutableList;
import org.junit.jupiter.api.Test;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class ByteArrayKeyUnitTest {
@Test
void givenPrimitiveByteArrayKey_whenRetrievingFromMap_shouldRetrieveDifferentObjects() {
// given
byte[] key1 = {1, 2, 3};
byte[] key2 = {1, 2, 3};
String value1 = "value1";
String value2 = "value2";
Map<byte[], String> map = new HashMap<>();
map.put(key1, value1);
map.put(key2, value2);
// when
String retrievedValue1 = map.get(key1);
String retrievedValue2 = map.get(key2);
String retrievedValue3 = map.get(new byte[]{1, 2, 3});
// then
assertThat(retrievedValue1).isEqualTo(value1);
assertThat(retrievedValue2).isEqualTo(value2);
assertThat(retrievedValue3).isNull();
}
@Test
void givenEncodedStringKey_whenRetrievingFromMap_shouldRetrieveLastPutObject() {
// given
String key1 = Base64.getEncoder().encodeToString(new byte[]{1, 2, 3});
String key2 = Base64.getEncoder().encodeToString(new byte[]{1, 2, 3});
String value1 = "value1";
String value2 = "value2";
Map<String, String> map = new HashMap<>();
map.put(key1, value1);
map.put(key2, value2);
// when
String retrievedValue1 = map.get(key1);
String retrievedValue2 = map.get(key2);
// then
assertThat(key1).isEqualTo(key2);
assertThat(retrievedValue1).isEqualTo(value2);
assertThat(retrievedValue2).isEqualTo(value2);
assertThat(retrievedValue1).isEqualTo(retrievedValue2);
}
@Test
void givenByteListKey_whenRetrievingFromMap_shouldRetrieveLastPutObject() {
// given
List<Byte> key1 = ImmutableList.of((byte)1, (byte)2, (byte)3);
List<Byte> key2 = ImmutableList.of((byte)1, (byte)2, (byte)3);
String value1 = "value1";
String value2 = "value2";
Map<List<Byte>, String> map = new HashMap<>();
map.put(key1, value1);
map.put(key2, value2);
// when
String retrievedValue1 = map.get(key1);
String retrievedValue2 = map.get(key2);
// then
assertThat(key1).isEqualTo(key2);
assertThat(retrievedValue1).isEqualTo(value2);
assertThat(retrievedValue2).isEqualTo(value2);
assertThat(retrievedValue1).isEqualTo(retrievedValue2);
}
@Test
void givenCustomWrapperKey_whenRetrievingFromMap_shouldRetrieveLastPutObject() {
// given
BytesKey key1 = new BytesKey(new byte[]{1, 2, 3});
BytesKey key2 = new BytesKey(new byte[]{1, 2, 3});
String value1 = "value1";
String value2 = "value2";
Map<BytesKey, String> map = new HashMap<>();
map.put(key1, value1);
map.put(key2, value2);
// when
String retrievedValue1 = map.get(key1);
String retrievedValue2 = map.get(key2);
String retrievedValue3 = map.get(new BytesKey(new byte[]{1, 2, 3}));
// then
assertThat(key1).isEqualTo(key2);
assertThat(retrievedValue1).isEqualTo(value2);
assertThat(retrievedValue2).isEqualTo(value2);
assertThat(retrievedValue1).isEqualTo(retrievedValue2);
assertThat(retrievedValue3).isEqualTo(value2);
}
}

View File

@ -6,22 +6,21 @@ import static org.junit.Assert.assertEquals;
public class PerfectSquareUnitTest {
@Test
public void test0xFFAssignedToInteger() {
public void testIsNumberPerfectSquare() {
long n = 18676209273604L; // 18676209273604 = 43621598 * 43621598
boolean expectedValue = true;
assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareByUsingSqrt(n));
assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareByUsingBinarySearch(1, Integer.MAX_VALUE, n));
assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareByUsingNewtonMethod(n));
assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareWithOptimization(n));
}
@Test
public void test0xFFAssignedToByte() {
long n = 549790047707L; // prime number
boolean expectedValue = false;
n = 549790047707L; // prime number
expectedValue = false;
assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareByUsingSqrt(n));
assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareByUsingBinarySearch(1, Integer.MAX_VALUE, n));
assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareByUsingNewtonMethod(n));
assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareWithOptimization(n));
}
}

View File

@ -1,3 +1,4 @@
### Relevant Articles:
- [Getting Database URL From JDBC Connection Object](https://www.baeldung.com/jdbc-get-url-from-connection)
- [JDBC URL Format For Different Databases](https://www.baeldung.com/java-jdbc-url-format)

View File

@ -20,10 +20,43 @@
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.driver.version}</version>
</dependency>
<!--
==================================================================
This jar is not in maven central repo due to some license issues.
We need to manually download and install to maven repository.
==================================================================
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>${oracle.driver.version}</version>
</dependency>
-->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>${mssql.driver.version}</version>
</dependency>
</dependencies>
<properties>
<h2.version>1.4.200</h2.version>
<postgresql.version>42.2.5.jre7</postgresql.version>
<mssql.driver.version>8.4.1.jre11</mssql.driver.version>
<oracle.driver.version>10.2.0.4.0</oracle.driver.version>
<mysql.driver.version>8.0.22</mysql.driver.version>
</properties>
</project>
</project>

View File

@ -0,0 +1,86 @@
package com.baeldung.jdbcurlformat;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import static org.junit.Assert.assertNotNull;
public class JdbcUrlFormatLiveTest {
@Test
public void givenOracleSID_thenCreateConnectionObject() {
String oracleJdbcUrl = "jdbc:oracle:thin:@myoracle.db.server:1521:my_sid";
String username = "dbUser";
String password = "1234567";
try (Connection conn = DriverManager.getConnection(oracleJdbcUrl, username, password)) {
assertNotNull(conn);
} catch (SQLException e) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
}
}
@Test
public void givenOracleServiceName_thenCreateConnectionObject() {
String oracleJdbcUrl = "jdbc:oracle:thin:@//myoracle.db.server:1521/my_servicename";
String username = "dbUser";
String password = "1234567";
try (Connection conn = DriverManager.getConnection(oracleJdbcUrl, username, password)) {
assertNotNull(conn);
} catch (SQLException e) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
}
}
@Test
public void givenOracleTnsnames_thenCreateConnectionObject() {
String oracleJdbcUrl = "jdbc:oracle:thin:@" +
"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)" +
"(HOST=myoracle.db.server)(PORT=1521))" +
"(CONNECT_DATA=(SERVICE_NAME=my_servicename)))";
String username = "dbUser";
String password = "1234567";
try (Connection conn = DriverManager.getConnection(oracleJdbcUrl, username, password)) {
assertNotNull(conn);
} catch (SQLException e) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
}
}
@Test
public void givenMysqlDb_thenCreateConnectionObject() {
String jdbcUrl = "jdbc:mysql://mysql.db.server:3306/my_database?useSSL=false&serverTimezone=UTC";
String username = "dbUser";
String password = "1234567";
try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) {
assertNotNull(conn);
} catch (SQLException e) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
}
}
@Test
public void givenMssqlDb_thenCreateConnectionObject() {
String jdbcUrl = "jdbc:sqlserver://mssql.db.server\\mssql_instance;databaseName=my_database";
String username = "dbUser";
String password = "1234567";
try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) {
assertNotNull(conn);
} catch (SQLException e) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
}
}
@Test
public void givenPostgreSqlDb_thenCreateConnectionObject() {
String jdbcUrl = "jdbc:postgresql://postgresql.db.server:5430/my_database?ssl=true&loglevel=2";
String username = "dbUser";
String password = "1234567";
try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) {
assertNotNull(conn);
} catch (SQLException e) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
}
}
}

View File

@ -662,8 +662,7 @@
<module>spring-mobile</module>
<module>spring-mockito</module>
<module>spring-mvc-basics</module>
<module>spring-mvc-basics-2</module>
<module>spring-mvc-basics-3</module>
<module>spring-mvc-basics-4</module>
@ -714,6 +713,7 @@
<module>spring-vault</module>
<module>spring-vertx</module>
<module>spring-web-modules</module>
<module>spring-webflux-amqp</module> <!-- long -->
<module>spring-websockets</module>
@ -1148,8 +1148,7 @@
<module>spring-mobile</module>
<module>spring-mockito</module>
<module>spring-mvc-basics</module>
<module>spring-mvc-basics-2</module>
<module>spring-mvc-basics-3</module>
<module>spring-mvc-basics-4</module>
@ -1199,6 +1198,7 @@
<module>spring-vault</module>
<module>spring-vertx</module>
<module>spring-web-modules</module>
<module>spring-webflux-amqp</module> <!-- long -->
<module>spring-websockets</module>

View File

@ -47,6 +47,17 @@
<artifactId>camel-spring-javaconfig</artifactId>
<version>${env.camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson</artifactId>
<version>${env.camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test</artifactId>
<version>${env.camel.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>

View File

@ -0,0 +1,24 @@
package com.baeldung.camel.jackson;
public class Fruit {
private String name;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.camel.jackson;
import java.util.List;
public class FruitList {
private List<Fruit> fruits;
public List<Fruit> getFruits() {
return fruits;
}
public void setFruits(List<Fruit> fruits) {
this.fruits = fruits;
}
}

View File

@ -0,0 +1,60 @@
package com.baeldung.camel.jackson;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.jackson.ListJacksonDataFormat;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;
public class FruitArrayJacksonUnmarshalUnitTest extends CamelTestSupport {
@Test
public void givenJsonFruitArray_whenUnmarshalled_thenSuccess() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:marshalledObject");
mock.expectedMessageCount(1);
mock.message(0).body().isInstanceOf(List.class);
String json = readJsonFromFile("/json/fruit-array.json");
template.sendBody("direct:jsonInput", json);
assertMockEndpointsSatisfied();
@SuppressWarnings("unchecked")
List<Fruit> fruitList = mock.getReceivedExchanges().get(0).getIn().getBody(List.class);
assertNotNull("Fruit lists should not be null", fruitList);
assertEquals("There should be two fruits", 2, fruitList.size());
Fruit fruit = fruitList.get(0);
assertEquals("Fruit name", "Banana", fruit.getName());
assertEquals("Fruit id", 100, fruit.getId());
fruit = fruitList.get(1);
assertEquals("Fruit name", "Apple", fruit.getName());
assertEquals("Fruit id", 101, fruit.getId());
}
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:jsonInput").unmarshal(new ListJacksonDataFormat(Fruit.class))
.to("mock:marshalledObject");
}
};
}
private String readJsonFromFile(String path) throws URISyntaxException, IOException {
URL resource = FruitArrayJacksonUnmarshalUnitTest.class.getResource(path);
return new String(Files.readAllBytes(Paths.get(resource.toURI())));
}
}

View File

@ -0,0 +1,59 @@
package com.baeldung.camel.jackson;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.jackson.JacksonDataFormat;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;
public class FruitListJacksonUnmarshalUnitTest extends CamelTestSupport {
@Test
public void givenJsonFruitList_whenUnmarshalled_thenSuccess() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:marshalledObject");
mock.expectedMessageCount(1);
mock.message(0).body().isInstanceOf(FruitList.class);
String json = readJsonFromFile("/json/fruit-list.json");
template.sendBody("direct:jsonInput", json);
assertMockEndpointsSatisfied();
FruitList fruitList = mock.getReceivedExchanges().get(0).getIn().getBody(FruitList.class);
assertNotNull("Fruit lists should not be null", fruitList);
List<Fruit> fruits = fruitList.getFruits();
assertEquals("There should be two fruits", 2, fruits.size());
Fruit fruit = fruits.get(0);
assertEquals("Fruit name", "Banana", fruit.getName());
assertEquals("Fruit id", 100, fruit.getId());
fruit = fruits.get(1);
assertEquals("Fruit name", "Apple", fruit.getName());
assertEquals("Fruit id", 101, fruit.getId());
}
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:jsonInput").unmarshal(new JacksonDataFormat(FruitList.class))
.to("mock:marshalledObject");
}
};
}
private String readJsonFromFile(String path) throws URISyntaxException, IOException {
URL resource = FruitListJacksonUnmarshalUnitTest.class.getResource(path);
return new String(Files.readAllBytes(Paths.get(resource.toURI())));
}
}

View File

@ -0,0 +1,10 @@
[
{
"id": 100,
"name": "Banana"
},
{
"id": 101,
"name": "Apple"
}
]

View File

@ -0,0 +1,12 @@
{
"fruits": [
{
"id": 100,
"name": "Banana"
},
{
"id": 101,
"name": "Apple"
}
]
}

View File

@ -69,6 +69,7 @@
<module>spring-boot-vue</module>
<module>spring-boot-xml</module>
<module>spring-boot-actuator</module>
<module>spring-boot-data-2</module>
</modules>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>spring-boot-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-data-2</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,13 @@
package com.baeldung.boot.jackson.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackages = "com.baeldung.boot.jackson.controller")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.boot.jackson.config;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class CoffeeConstants {
public static final String DATETIME_FORMAT = "dd-MM-yyyy HH:mm";
public static final LocalDateTime FIXED_DATE = LocalDateTime.now();
public static LocalDateTimeSerializer LOCAL_DATETIME_SERIALIZER = new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATETIME_FORMAT));
}

View File

@ -0,0 +1,18 @@
package com.baeldung.boot.jackson.config;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
@Configuration
public class CoffeeCustomizerConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL)
.serializers(LOCAL_DATETIME_SERIALIZER);
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.boot.jackson.config;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
@Configuration
public class CoffeeHttpConverterConfiguration {
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
.serializers(LOCAL_DATETIME_SERIALIZER)
.serializationInclusion(JsonInclude.Include.NON_NULL);
return new MappingJackson2HttpMessageConverter(builder.build());
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.boot.jackson.config;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
@Configuration
public class CoffeeJacksonBuilderConfig {
@Bean
@Primary
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
return new Jackson2ObjectMapperBuilder()
.serializers(LOCAL_DATETIME_SERIALIZER)
.serializationInclusion(JsonInclude.Include.NON_NULL);
}
}

View File

@ -0,0 +1,23 @@
package com.baeldung.boot.jackson.config;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
@Configuration
public class CoffeeObjectMapperConfig {
@Bean
@Primary
public ObjectMapper objectMapper() {
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(LOCAL_DATETIME_SERIALIZER);
return new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL)
.registerModule(module);
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.boot.jackson.config;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
@Configuration
@PropertySource("classpath:coffee.properties")
public class CoffeeRegisterModuleConfig {
@Bean
public Module javaTimeModule() {
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(LOCAL_DATETIME_SERIALIZER);
return module;
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.boot.jackson.controller;
import com.baeldung.boot.jackson.model.Coffee;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import static com.baeldung.boot.jackson.config.CoffeeConstants.FIXED_DATE;
@RestController
public class CoffeeController {
@GetMapping("/coffee")
public Coffee getCoffee(
@RequestParam(required = false) String brand,
@RequestParam(required = false) String name) {
return new Coffee().setBrand(brand)
.setDate(FIXED_DATE)
.setName(name);
}
}

View File

@ -0,0 +1,39 @@
package com.baeldung.boot.jackson.model;
import java.time.LocalDateTime;
public class Coffee {
private String name;
private String brand;
private LocalDateTime date;
public String getName() {
return name;
}
public Coffee setName(String name) {
this.name = name;
return this;
}
public String getBrand() {
return brand;
}
public Coffee setBrand(String brand) {
this.brand = brand;
return this;
}
public LocalDateTime getDate() {
return date;
}
public Coffee setDate(LocalDateTime date) {
this.date = date;
return this;
}
}

View File

@ -0,0 +1 @@
spring.jackson.default-property-inclusion=non_null

View File

@ -0,0 +1,33 @@
package com.baeldung.boot.jackson.app;
import com.baeldung.boot.jackson.config.CoffeeConstants;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import java.time.format.DateTimeFormatter;
import static com.baeldung.boot.jackson.config.CoffeeConstants.FIXED_DATE;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public abstract class AbstractCoffeeIntegrationTest {
@Autowired
protected TestRestTemplate restTemplate;
@Test
public void whenGetCoffee_thenSerializedWithDateAndNonNull() {
String formattedDate = DateTimeFormatter.ofPattern(CoffeeConstants.DATETIME_FORMAT)
.format(FIXED_DATE);
String brand = "Lavazza";
String url = "/coffee?brand=" + brand;
String response = restTemplate.getForObject(url, String.class);
assertThat(response).isEqualTo(
"{\"brand\":\"" + brand + "\",\"date\":\"" + formattedDate + "\"}");
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.boot.jackson.app;
import com.baeldung.boot.jackson.config.CoffeeCustomizerConfig;
import org.springframework.context.annotation.Import;
@Import(CoffeeCustomizerConfig.class)
public class CoffeeCustomizerIntegrationTest extends AbstractCoffeeIntegrationTest {
}

View File

@ -0,0 +1,8 @@
package com.baeldung.boot.jackson.app;
import com.baeldung.boot.jackson.config.CoffeeHttpConverterConfiguration;
import org.springframework.context.annotation.Import;
@Import(CoffeeHttpConverterConfiguration.class)
public class CoffeeHttpConverterIntegrationTest extends AbstractCoffeeIntegrationTest {
}

View File

@ -0,0 +1,8 @@
package com.baeldung.boot.jackson.app;
import com.baeldung.boot.jackson.config.CoffeeJacksonBuilderConfig;
import org.springframework.context.annotation.Import;
@Import(CoffeeJacksonBuilderConfig.class)
public class CoffeeJacksonBuilderIntegrationTest extends AbstractCoffeeIntegrationTest {
}

View File

@ -0,0 +1,8 @@
package com.baeldung.boot.jackson.app;
import com.baeldung.boot.jackson.config.CoffeeObjectMapperConfig;
import org.springframework.context.annotation.Import;
@Import(CoffeeObjectMapperConfig.class)
public class CoffeeObjectMapperIntegrationTest extends AbstractCoffeeIntegrationTest {
}

View File

@ -0,0 +1,8 @@
package com.baeldung.boot.jackson.app;
import com.baeldung.boot.jackson.config.CoffeeRegisterModuleConfig;
import org.springframework.context.annotation.Import;
@Import(CoffeeRegisterModuleConfig.class)
public class CoffeeRegisterModuleIntegrationTest extends AbstractCoffeeIntegrationTest {
}

View File

@ -15,7 +15,7 @@ public class ReloadablePropertySource extends PropertySource {
}
public ReloadablePropertySource(String name, String path) {
super(StringUtils.isEmpty(name) ? path : name);
super(StringUtils.hasText(name) ? path : name);
try {
this.propertiesConfiguration = new PropertiesConfiguration(path);
FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();

View File

@ -6,7 +6,9 @@ spring:
---
spring:
profiles: test
config:
activate:
on-profile: test
name: test-YAML
environment: testing
enabled: false
@ -37,7 +39,9 @@ component:
---
spring:
profiles: prod
config:
activate:
on-profile: prod
name: prod-YAML
environment: production
enabled: true
@ -48,7 +52,9 @@ servers:
---
spring:
profiles: dev
config:
activate:
on-profile: dev
name: ${DEV_NAME:dev-YAML}
environment: development
enabled: true

View File

@ -19,6 +19,7 @@
<module>spring-cloud-eureka-server</module>
<module>spring-cloud-eureka-client</module>
<module>spring-cloud-eureka-feign-client</module>
<module>spring-cloud-eureka-feign-client-integration-test</module>
</modules>
<dependencies>

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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>
<artifactId>spring-cloud-eureka-feign-client-integration-test</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>spring-cloud-eureka-feign-client-integration-test</name>
<packaging>jar</packaging>
<description>Spring Cloud Eureka - Feign Client Integration Tests</description>
<parent>
<groupId>com.baeldung.spring.cloud</groupId>
<artifactId>spring-cloud-eureka</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>${junit-jupiter.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>${spring-cloud-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>2.27.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.14.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>4.0.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,15 @@
package com.baeldung.spring.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,16 @@
package com.baeldung.spring.cloud.client;
import com.baeldung.spring.cloud.model.Book;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@FeignClient("books-service")
//@FeignClient(value="simple-books-client", url="${book.service.url}")
public interface BooksClient {
@RequestMapping("/books")
List<Book> getBooks();
}

View File

@ -0,0 +1,15 @@
package com.baeldung.spring.cloud.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private String title;
private String author;
}

View File

@ -0,0 +1,27 @@
package com.baeldung.spring.cloud.client;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import java.io.IOException;
import static java.nio.charset.Charset.defaultCharset;
import static org.springframework.util.StreamUtils.copyToString;
public class BookMocks {
public static void setupMockBooksResponse(WireMockServer mockService) throws IOException {
mockService.stubFor(WireMock.get(WireMock.urlEqualTo("/books"))
.willReturn(
WireMock.aResponse()
.withStatus(HttpStatus.OK.value())
.withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
.withBody(
copyToString(
BookMocks.class.getClassLoader().getResourceAsStream("payload/get-books-response.json"),
defaultCharset()))));
}
}

View File

@ -0,0 +1,53 @@
package com.baeldung.spring.cloud.client;
import com.baeldung.spring.cloud.model.Book;
import com.github.tomakehurst.wiremock.WireMockServer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.io.IOException;
import static com.baeldung.spring.cloud.client.BookMocks.setupMockBooksResponse;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@SpringBootTest
@ActiveProfiles("test")
@EnableConfigurationProperties
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { WireMockConfig.class })
class BooksClientIntegrationTest {
@Autowired
private WireMockServer mockBooksService;
@Autowired
private BooksClient booksClient;
@BeforeEach
void setUp() throws IOException {
setupMockBooksResponse(mockBooksService);
}
@Test
public void whenGetBooks_thenBooksShouldBeReturned() {
assertFalse(booksClient.getBooks().isEmpty());
}
@Test
public void whenGetBooks_thenTheCorrectBooksShouldBeReturned() {
assertTrue(booksClient.getBooks()
.containsAll(asList(
new Book("Dune", "Frank Herbert"),
new Book("Foundation", "Isaac Asimov"))));
}
}

View File

@ -0,0 +1,39 @@
package com.baeldung.spring.cloud.client;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.ActiveProfiles;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.lifecycle.Startables;
import java.util.stream.Stream;
@TestConfiguration
@ActiveProfiles("eureka-test")
public class EurekaContainerConfig {
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
public static GenericContainer eurekaServer
= new GenericContainer("springcloud/eureka")
.withExposedPorts(8761);
@Override
public void initialize(@NotNull ConfigurableApplicationContext configurableApplicationContext) {
Startables.deepStart(Stream.of(eurekaServer)).join();
TestPropertyValues
.of("eureka.client.serviceUrl.defaultZone=http://localhost:"
+ eurekaServer.getFirstMappedPort().toString()
+ "/eureka")
.applyTo(configurableApplicationContext);
}
}
}

View File

@ -0,0 +1,65 @@
package com.baeldung.spring.cloud.client;
import com.baeldung.spring.cloud.model.Book;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.io.IOException;
import static com.baeldung.spring.cloud.client.BookMocks.setupMockBooksResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.moreThan;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.assertTrue;
@SpringBootTest
@ActiveProfiles("ribbon-test")
@EnableConfigurationProperties
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { RibbonTestConfig.class })
class LoadBalancerBooksClientIntegrationTest {
@Autowired
private WireMockServer mockBooksService;
@Autowired
private WireMockServer secondMockBooksService;
@Autowired
private BooksClient booksClient;
@BeforeEach
void setUp() throws IOException {
setupMockBooksResponse(mockBooksService);
setupMockBooksResponse(secondMockBooksService);
}
@Test
void whenGetBooks_thenRequestsAreLoadBalanced() {
for (int k = 0; k < 10; k++) {
booksClient.getBooks();
}
mockBooksService.verify(
moreThan(0), getRequestedFor(WireMock.urlEqualTo("/books")));
secondMockBooksService.verify(
moreThan(0), getRequestedFor(WireMock.urlEqualTo("/books")));
}
@Test
public void whenGetBooks_thenTheCorrectBooksShouldBeReturned() {
assertTrue(booksClient.getBooks()
.containsAll(asList(
new Book("Dune", "Frank Herbert"),
new Book("Foundation", "Isaac Asimov"))));
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.spring.cloud.client;
import com.baeldung.spring.cloud.model.Book;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
@Configuration
@RestController
@ActiveProfiles("eureka-test")
public class MockBookServiceConfig {
@RequestMapping("/books")
public List<Book> getBooks() {
return Collections.singletonList(new Book("Hitchhiker's guide to the galaxy", "Douglas Adams"));
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.spring.cloud.client;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.ActiveProfiles;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
@TestConfiguration
@ActiveProfiles("ribbon-test")
public class RibbonTestConfig {
@Autowired
private WireMockServer mockBooksService;
@Autowired
private WireMockServer secondMockBooksService;
@Bean(initMethod = "start", destroyMethod = "stop")
public WireMockServer mockBooksService() {
return new WireMockServer(options().dynamicPort());
}
@Bean(name="secondMockBooksService", initMethod = "start", destroyMethod = "stop")
public WireMockServer secondBooksMockService() {
return new WireMockServer(options().dynamicPort());
}
@Bean
public ServerList<Server> ribbonServerList() {
return new StaticServerList<>(
new Server("localhost", mockBooksService.port()),
new Server("localhost", secondMockBooksService.port()));
}
}

View File

@ -0,0 +1,52 @@
package com.baeldung.spring.cloud.client;
import com.baeldung.spring.cloud.Application;
import com.baeldung.spring.cloud.model.Book;
import com.netflix.discovery.EurekaClient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Lazy;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.List;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.awaitility.Awaitility.await;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ActiveProfiles("eureka-test")
@EnableConfigurationProperties
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = { MockBookServiceConfig.class }, initializers = { EurekaContainerConfig.Initializer.class })
class ServiceDiscoveryBooksClientIntegrationTest {
@Autowired
private BooksClient booksClient;
@Lazy
@Autowired
private EurekaClient eurekaClient;
@BeforeEach
void setUp() {
await().atMost(60, SECONDS).until(() -> eurekaClient.getApplications().size() > 0);
}
@Test
public void whenGetBooks_thenTheCorrectBooksAreReturned() {
List<Book> books = booksClient.getBooks();
assertEquals(1, books.size());
assertEquals(
new Book("Hitchhiker's guide to the galaxy", "Douglas Adams"),
books.stream().findFirst().get());
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.spring.cloud.client;
import com.github.tomakehurst.wiremock.WireMockServer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.ActiveProfiles;
@TestConfiguration
@ActiveProfiles("test")
public class WireMockConfig {
@Bean(initMethod = "start", destroyMethod = "stop")
public WireMockServer mockBooksService() {
return new WireMockServer(9561);
}
}

View File

@ -0,0 +1,11 @@
#book:
# service:
# url: http://localhost:9561
books-service:
ribbon:
listOfServers: http://localhost:9561
eureka:
client:
enabled: false

View File

@ -0,0 +1,10 @@
[
{
"title": "Dune",
"author": "Frank Herbert"
},
{
"title": "Foundation",
"author": "Isaac Asimov"
}
]

View File

@ -71,16 +71,16 @@
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
</project>

View File

@ -0,0 +1,16 @@
package com.baeldung.resttemplate.json.consumer.service;
import java.util.List;
public interface UserConsumerService {
List<String> processUserDataFromObjectArray();
List<String> processUserDataFromUserArray();
List<String> processUserDataFromUserList();
List<String> processNestedUserDataFromUserArray();
List<String> processNestedUserDataFromUserList();
}

View File

@ -0,0 +1,90 @@
package com.baeldung.resttemplate.json.consumer.service;
import com.baeldung.resttemplate.json.model.Address;
import com.baeldung.resttemplate.json.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class UserConsumerServiceImpl implements UserConsumerService {
private static final String BASE_URL = "http://localhost:8080/users";
private final RestTemplate restTemplate;
private static final ObjectMapper mapper = new ObjectMapper();
public UserConsumerServiceImpl(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public List<String> processUserDataFromObjectArray() {
ResponseEntity<Object[]> responseEntity = restTemplate.getForEntity(BASE_URL, Object[].class);
Object[] objects = responseEntity.getBody();
return Arrays.stream(objects)
.map(object -> mapper.convertValue(object, User.class))
.map(User::getName)
.collect(Collectors.toList());
}
@Override
public List<String> processUserDataFromUserArray() {
ResponseEntity<User[]> responseEntity = restTemplate.getForEntity(BASE_URL, User[].class);
User[] userArray = responseEntity.getBody();
return Arrays.stream(userArray)
.map(User::getName)
.collect(Collectors.toList());
}
@Override
public List<String> processUserDataFromUserList() {
ResponseEntity<List<User>> responseEntity =
restTemplate.exchange(
BASE_URL,
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<User>>() {}
);
List<User> users = responseEntity.getBody();
return users.stream()
.map(User::getName)
.collect(Collectors.toList());
}
@Override
public List<String> processNestedUserDataFromUserArray() {
ResponseEntity<User[]> responseEntity = restTemplate.getForEntity(BASE_URL, User[].class);
User[] userArray = responseEntity.getBody();
//we can get more info if we need :
MediaType contentType = responseEntity.getHeaders().getContentType();
HttpStatus statusCode = responseEntity.getStatusCode();
return Arrays.stream(userArray)
.flatMap(user -> user.getAddressList().stream())
.map(Address::getPostCode)
.collect(Collectors.toList());
}
@Override
public List<String> processNestedUserDataFromUserList() {
ResponseEntity<List<User>> responseEntity =
restTemplate.exchange(
BASE_URL,
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<User>>() {}
);
List<User> userList = responseEntity.getBody();
return userList.stream()
.flatMap(user -> user.getAddressList().stream())
.map(Address::getPostCode)
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.resttemplate.json.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Address {
private final String addressLine1;
private final String addressLine2;
private final String town;
private final String postCode;
@JsonCreator
public Address(
@JsonProperty("addressLine1") String addressLine1,
@JsonProperty("addressLine2") String addressLine2,
@JsonProperty("town") String town,
@JsonProperty("postCode") String postCode) {
this.addressLine1 = addressLine1;
this.addressLine2 = addressLine2;
this.town = town;
this.postCode = postCode;
}
public String getPostCode() {
return postCode;
}
}

View File

@ -0,0 +1,30 @@
package com.baeldung.resttemplate.json.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User {
private final int id;
private final String name;
private final List<Address> addressList;
@JsonCreator
public User(
@JsonProperty("id") int id,
@JsonProperty("name") String name,
@JsonProperty("addressList") List<Address> addressList) {
this.id = id;
this.name = name;
this.addressList = addressList;
}
public String getName() {
return name;
}
public List<Address> getAddressList() { return addressList; }
}

View File

@ -0,0 +1,127 @@
package com.baeldung.resttemplate.json.consumer.service;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.test.web.client.ExpectedCount;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
@SpringBootTest
public class UserConsumerServiceImplUnitTest {
private static String USER_JSON = "[{\"id\":1,\"name\":\"user1\",\"addressList\":[{\"addressLine1\":\"address1_addressLine1\",\"addressLine2\":\"address1_addressLine2\",\"town\":\"address1_town\",\"postCode\":\"user1_address1_postCode\"}," +
"{\"addressLine1\":\"address2_addressLine1\",\"addressLine2\":\"address2_addressLine2\",\"town\":\"address2_town\",\"postCode\":\"user1_address2_postCode\"}]}," +
"{\"id\":2,\"name\":\"user2\",\"addressList\":[{\"addressLine1\":\"address1_addressLine1\",\"addressLine2\":\"address1_addressLine2\",\"town\":\"address1_town\",\"postCode\":\"user2_address1_postCode\"}]}]";
private MockRestServiceServer mockServer;
private final RestTemplate restTemplate = new RestTemplate();
private final UserConsumerService tested = new UserConsumerServiceImpl(restTemplate);
@Before
public void init() {
mockServer = MockRestServiceServer.createServer(restTemplate);
}
@Test
public void whenProcessUserDataAsObjects_thenOK() {
String url = "http://localhost:8080/users";
List<String> expected = Arrays.asList("user1", "user2");
mockServer.expect(ExpectedCount.once(),
requestTo(url))
.andExpect(method(HttpMethod.GET))
.andRespond(withStatus(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(USER_JSON));
List<String> actual = tested.processUserDataFromObjectArray();
mockServer.verify();
assertThat(actual).containsExactly(expected.get(0), expected.get(1));
}
@Test
public void whenProcessUserDataAsArray_thenOK() {
String url = "http://localhost:8080/users";
List<String> expected = Arrays.asList("user1", "user2");
mockServer.expect(ExpectedCount.once(),
requestTo(url))
.andExpect(method(HttpMethod.GET))
.andRespond(withStatus(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(USER_JSON));
List<String> actual = tested.processUserDataFromUserArray();
mockServer.verify();
assertThat(actual).containsExactly(expected.get(0), expected.get(1));
}
@Test
public void whenProcessUserDataAsList_thenOK() {
String url = "http://localhost:8080/users";
List<String> expected = Arrays.asList("user1", "user2");
mockServer.expect(ExpectedCount.once(),
requestTo(url))
.andExpect(method(HttpMethod.GET))
.andRespond(withStatus(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(USER_JSON));
List<String> actual = tested.processUserDataFromUserList();
mockServer.verify();
assertThat(actual).containsExactly(expected.get(0), expected.get(1));
}
@Test
public void whenProcessNestedUserDataFromArray_thenOK() {
String url = "http://localhost:8080/users";
List<String> expected = Arrays.asList("user1_address1_postCode", "user1_address2_postCode", "user2_address1_postCode");
mockServer.expect(ExpectedCount.once(),
requestTo(url))
.andExpect(method(HttpMethod.GET))
.andRespond(withStatus(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(USER_JSON));
List<String> actual = tested.processNestedUserDataFromUserArray();
mockServer.verify();
assertThat(actual).containsExactly(expected.get(0), expected.get(1), expected.get(2));
}
@Test
public void whenProcessNestedUserDataFromList_thenOK() {
String url = "http://localhost:8080/users";
List<String> expected = Arrays.asList("user1_address1_postCode", "user1_address2_postCode", "user2_address1_postCode");
mockServer.expect(ExpectedCount.once(),
requestTo(url))
.andExpect(method(HttpMethod.GET))
.andRespond(withStatus(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(USER_JSON));
List<String> actual = tested.processNestedUserDataFromUserList();
mockServer.verify();
assertThat(actual).containsExactly(expected.get(0), expected.get(1), expected.get(2));
}
}

View File

@ -0,0 +1,20 @@
<?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>
<artifactId>spring-web-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-web-modules</name>
<packaging>pom</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modules>
<module>spring-mvc-basics</module>
</modules>
</project>

View File

@ -4,7 +4,7 @@ This module contains articles about the basics of Spring MVC. Articles about mor
their own module.
### The Course
The "REST With Spring" Classes: http://bit.ly/restwithspring
The "REST With Spring" Classes: https://bit.ly/restwithspring
### Relevant Articles:
- [Spring MVC Tutorial](https://www.baeldung.com/spring-mvc-tutorial)

View File

@ -12,7 +12,7 @@
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-boot-2</relativePath>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<dependencies>

Some files were not shown because too many files have changed in this diff Show More