commit
923df780df
@ -13,22 +13,22 @@ public class KadaneAlgorithm {
|
|||||||
int start = 0;
|
int start = 0;
|
||||||
int end = 0;
|
int end = 0;
|
||||||
|
|
||||||
int maxSoFar = 0, maxEndingHere = 0;
|
int maxSoFar = arr[0], maxEndingHere = arr[0];
|
||||||
|
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
|
|
||||||
if (arr[i] > maxEndingHere + arr[i]) {
|
if (arr[i] > maxEndingHere + arr[i]) {
|
||||||
start = i;
|
start = i;
|
||||||
maxEndingHere = arr[i];
|
maxEndingHere = arr[i];
|
||||||
} else
|
} else {
|
||||||
maxEndingHere = maxEndingHere + arr[i];
|
maxEndingHere = maxEndingHere + arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
if (maxSoFar < maxEndingHere) {
|
if (maxSoFar < maxEndingHere) {
|
||||||
maxSoFar = maxEndingHere;
|
maxSoFar = maxEndingHere;
|
||||||
end = i;
|
end = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.info("Found Maximum Subarray between {} and {}", start, end);
|
logger.info("Found Maximum Subarray between {} and {}", Math.min(start, end), end);
|
||||||
return maxSoFar;
|
return maxSoFar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,22 @@ class KadaneAlgorithmUnitTest {
|
|||||||
@Test
|
@Test
|
||||||
void givenArrayWithNegativeNumberWhenMaximumSubarrayThenReturns6() {
|
void givenArrayWithNegativeNumberWhenMaximumSubarrayThenReturns6() {
|
||||||
//given
|
//given
|
||||||
int[] arr = new int[]{-3, 1, -8, 4, -1, 2, 1, -5, 5};
|
int[] arr = new int[] { -3, 1, -8, 4, -1, 2, 1, -5, 5 };
|
||||||
//when
|
//when
|
||||||
KadaneAlgorithm algorithm = new KadaneAlgorithm();
|
KadaneAlgorithm algorithm = new KadaneAlgorithm();
|
||||||
int maxSum = algorithm.maxSubArraySum(arr);
|
int maxSum = algorithm.maxSubArraySum(arr);
|
||||||
//then
|
//then
|
||||||
assertEquals(6, maxSum);
|
assertEquals(6, maxSum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenArrayWithAllNegativeNumbersWhenMaximumSubarrayThenReturnsExpectedResult() {
|
||||||
|
//given
|
||||||
|
int[] arr = new int[] { -8, -7, -5, -4, -3, -1, -2 };
|
||||||
|
//when
|
||||||
|
KadaneAlgorithm algorithm = new KadaneAlgorithm();
|
||||||
|
int maxSum = algorithm.maxSubArraySum(arr);
|
||||||
|
//then
|
||||||
|
assertEquals(-1, maxSum);
|
||||||
|
}
|
||||||
}
|
}
|
@ -24,6 +24,12 @@
|
|||||||
<artifactId>jmh-generator-annprocess</artifactId>
|
<artifactId>jmh-generator-annprocess</artifactId>
|
||||||
<version>${jmh.version}</version>
|
<version>${jmh.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<version>3.19.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -2,7 +2,6 @@ package com.baeldung.genericarrays;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
package com.baeldung.genericarrays;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
|
public class StreamToArrayUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAStream_thenCanGetArrayOfObject() {
|
||||||
|
Object[] strings = Stream.of("A", "AAA", "B", "AAB", "C")
|
||||||
|
.filter(string -> string.startsWith("A"))
|
||||||
|
.toArray();
|
||||||
|
|
||||||
|
assertThat(strings).containsExactly("A", "AAA", "AAB");
|
||||||
|
assertThat(strings).isNotInstanceOf(String[].class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAStream_thenCanGetArrayOfString() {
|
||||||
|
String[] strings = Stream.of("A", "AAA", "B", "AAB", "C")
|
||||||
|
.filter(string -> string.startsWith("A"))
|
||||||
|
.toArray(String[]::new);
|
||||||
|
|
||||||
|
assertThat(strings).containsExactly("A", "AAA", "AAB");
|
||||||
|
assertThat(strings).isInstanceOf(String[].class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test
|
||||||
|
public void givenAStream_whenConvertToOptional_thenCanGetArrayOfOptional() {
|
||||||
|
Stream<Optional<String>> stream = Stream.of("A", "AAA", "B", "AAB", "C")
|
||||||
|
.filter(string -> string.startsWith("A"))
|
||||||
|
.map(Optional::of);
|
||||||
|
Optional<String>[] strings = stream
|
||||||
|
.toArray(Optional[]::new);
|
||||||
|
|
||||||
|
assertThat(strings).containsExactly(Optional.of("A"),
|
||||||
|
Optional.of("AAA"),
|
||||||
|
Optional.of("AAB"));
|
||||||
|
assertThat(strings).isInstanceOf(Optional[].class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAStream_whenConvertToOptional_thenCanGetArrayOfOptionalWithHelper() {
|
||||||
|
Optional<String>[] strings = Stream.of("A", "AAA", "B", "AAB", "C")
|
||||||
|
.filter(string -> string.startsWith("A"))
|
||||||
|
.map(Optional::of)
|
||||||
|
.toArray(genericArray(Optional[]::new));
|
||||||
|
|
||||||
|
assertThat(strings).containsExactly(Optional.of("A"),
|
||||||
|
Optional.of("AAA"),
|
||||||
|
Optional.of("AAB"));
|
||||||
|
assertThat(strings).isInstanceOf(Optional[].class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInvalidUseOfGenericArray_thenIllegalCast() {
|
||||||
|
assertThatThrownBy(() -> {
|
||||||
|
ArrayList<String>[] lists = Stream.of(singletonList("A"))
|
||||||
|
.toArray(genericArray(List[]::new));
|
||||||
|
}).isInstanceOf(ClassCastException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static <T, R extends T> IntFunction<R[]> genericArray(IntFunction<T[]> arrayCreator) {
|
||||||
|
return size -> (R[])arrayCreator.apply(size);
|
||||||
|
}
|
||||||
|
}
|
@ -77,7 +77,6 @@
|
|||||||
<assertj.version>3.6.1</assertj.version>
|
<assertj.version>3.6.1</assertj.version>
|
||||||
<!-- instrumentation -->
|
<!-- instrumentation -->
|
||||||
<javaassist.version>3.27.0-GA</javaassist.version>
|
<javaassist.version>3.27.0-GA</javaassist.version>
|
||||||
<esapi.version>2.1.0.1</esapi.version>
|
|
||||||
<sun.tools.version>1.8.0</sun.tools.version>
|
<sun.tools.version>1.8.0</sun.tools.version>
|
||||||
<jol-core.version>0.10</jol-core.version>
|
<jol-core.version>0.10</jol-core.version>
|
||||||
<asm.version>8.0.1</asm.version>
|
<asm.version>8.0.1</asm.version>
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
This module contains articles about core features in the Java language
|
This module contains articles about core features in the Java language
|
||||||
|
|
||||||
- TODO
|
- [The Java final Keyword – Impact on Performance](https://www.baeldung.com/java-final-performance)
|
||||||
|
@ -47,6 +47,7 @@ public class Outer {
|
|||||||
// Anonymous Inner class extending a class
|
// Anonymous Inner class extending a class
|
||||||
public String greet() {
|
public String greet() {
|
||||||
Outer anonymous = new Outer() {
|
Outer anonymous = new Outer() {
|
||||||
|
@Override
|
||||||
public String greet() {
|
public String greet() {
|
||||||
return "Running Anonymous Class...";
|
return "Running Anonymous Class...";
|
||||||
}
|
}
|
||||||
@ -58,6 +59,7 @@ public class Outer {
|
|||||||
public String greet(String name) {
|
public String greet(String name) {
|
||||||
|
|
||||||
HelloWorld helloWorld = new HelloWorld() {
|
HelloWorld helloWorld = new HelloWorld() {
|
||||||
|
@Override
|
||||||
public String greet(String name) {
|
public String greet(String name) {
|
||||||
return "Welcome to " + name;
|
return "Welcome to " + name;
|
||||||
}
|
}
|
||||||
@ -68,8 +70,9 @@ public class Outer {
|
|||||||
|
|
||||||
// Anonymous inner class implementing nested interface
|
// Anonymous inner class implementing nested interface
|
||||||
public String greetSomeone(String name) {
|
public String greetSomeone(String name) {
|
||||||
|
|
||||||
HelloSomeone helloSomeOne = new HelloSomeone() {
|
HelloSomeone helloSomeOne = new HelloSomeone() {
|
||||||
|
@Override
|
||||||
public String greet(String name) {
|
public String greet(String name) {
|
||||||
return "Hello " + name;
|
return "Hello " + name;
|
||||||
}
|
}
|
||||||
@ -94,7 +97,8 @@ interface HelloWorld {
|
|||||||
public String greet(String name);
|
public String greet(String name);
|
||||||
|
|
||||||
// Nested class within an interface
|
// Nested class within an interface
|
||||||
class InnerClass {
|
class InnerClass implements HelloWorld {
|
||||||
|
@Override
|
||||||
public String greet(String name) {
|
public String greet(String name) {
|
||||||
return "Inner class within an interface";
|
return "Inner class within an interface";
|
||||||
}
|
}
|
||||||
|
@ -148,48 +148,46 @@ public class BinaryTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void traverseInOrderWithoutRecursion() {
|
public void traverseInOrderWithoutRecursion() {
|
||||||
Stack<Node> stack = new Stack<Node>();
|
Stack<Node> stack = new Stack<>();
|
||||||
|
Node current = root;
|
||||||
|
|
||||||
|
while (current != null || !stack.isEmpty()) {
|
||||||
|
while (current != null) {
|
||||||
|
stack.push(current);
|
||||||
|
current = current.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node top = stack.pop();
|
||||||
|
visit(top.value);
|
||||||
|
current = top.right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void traversePreOrderWithoutRecursion() {
|
||||||
|
Stack<Node> stack = new Stack<>();
|
||||||
Node current = root;
|
Node current = root;
|
||||||
stack.push(root);
|
stack.push(root);
|
||||||
while(! stack.isEmpty()) {
|
|
||||||
while(current.left != null) {
|
while (current != null && !stack.isEmpty()) {
|
||||||
current = current.left;
|
|
||||||
stack.push(current);
|
|
||||||
}
|
|
||||||
current = stack.pop();
|
current = stack.pop();
|
||||||
visit(current.value);
|
visit(current.value);
|
||||||
if(current.right != null) {
|
|
||||||
current = current.right;
|
if (current.right != null)
|
||||||
stack.push(current);
|
stack.push(current.right);
|
||||||
}
|
|
||||||
|
if (current.left != null)
|
||||||
|
stack.push(current.left);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void traversePreOrderWithoutRecursion() {
|
|
||||||
Stack<Node> stack = new Stack<Node>();
|
|
||||||
Node current = root;
|
|
||||||
stack.push(root);
|
|
||||||
while(! stack.isEmpty()) {
|
|
||||||
current = stack.pop();
|
|
||||||
visit(current.value);
|
|
||||||
|
|
||||||
if(current.right != null)
|
|
||||||
stack.push(current.right);
|
|
||||||
|
|
||||||
if(current.left != null)
|
|
||||||
stack.push(current.left);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void traversePostOrderWithoutRecursion() {
|
public void traversePostOrderWithoutRecursion() {
|
||||||
Stack<Node> stack = new Stack<Node>();
|
Stack<Node> stack = new Stack<>();
|
||||||
Node prev = root;
|
Node prev = root;
|
||||||
Node current = root;
|
Node current = root;
|
||||||
stack.push(root);
|
stack.push(root);
|
||||||
|
|
||||||
while (!stack.isEmpty()) {
|
while (current != null && !stack.isEmpty()) {
|
||||||
current = stack.peek();
|
current = stack.peek();
|
||||||
boolean hasChild = (current.left != null || current.right != null);
|
boolean hasChild = (current.left != null || current.right != null);
|
||||||
boolean isPrevLastChild = (prev == current.right || (prev == current.left && current.right == null));
|
boolean isPrevLastChild = (prev == current.right || (prev == current.left && current.right == null));
|
||||||
|
@ -13,7 +13,7 @@ public class BinaryTreeUnitTest {
|
|||||||
|
|
||||||
BinaryTree bt = createBinaryTree();
|
BinaryTree bt = createBinaryTree();
|
||||||
|
|
||||||
assertTrue(!bt.isEmpty());
|
assertFalse(bt.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -72,6 +72,7 @@ public class BinaryTreeUnitTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void it_deletes_the_root() {
|
public void it_deletes_the_root() {
|
||||||
|
|
||||||
int value = 12;
|
int value = 12;
|
||||||
BinaryTree bt = new BinaryTree();
|
BinaryTree bt = new BinaryTree();
|
||||||
bt.add(value);
|
bt.add(value);
|
||||||
@ -91,6 +92,14 @@ public class BinaryTreeUnitTest {
|
|||||||
bt.traverseInOrderWithoutRecursion();
|
bt.traverseInOrderWithoutRecursion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAnEmptyBinaryTree_WhenTraversingInOrderWithoutRecursion_ThenNoException() {
|
||||||
|
|
||||||
|
BinaryTree empty = new BinaryTree();
|
||||||
|
|
||||||
|
empty.traverseInOrderWithoutRecursion();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenABinaryTree_WhenTraversingPreOrder_ThenPrintValues() {
|
public void givenABinaryTree_WhenTraversingPreOrder_ThenPrintValues() {
|
||||||
|
|
||||||
@ -101,6 +110,14 @@ public class BinaryTreeUnitTest {
|
|||||||
bt.traversePreOrderWithoutRecursion();
|
bt.traversePreOrderWithoutRecursion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAnEmptyBinaryTree_WhenTraversingPreOrderWithoutRecursion_ThenNoException() {
|
||||||
|
|
||||||
|
BinaryTree empty = new BinaryTree();
|
||||||
|
|
||||||
|
empty.traversePreOrderWithoutRecursion();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenABinaryTree_WhenTraversingPostOrder_ThenPrintValues() {
|
public void givenABinaryTree_WhenTraversingPostOrder_ThenPrintValues() {
|
||||||
|
|
||||||
@ -111,6 +128,14 @@ public class BinaryTreeUnitTest {
|
|||||||
bt.traversePostOrderWithoutRecursion();
|
bt.traversePostOrderWithoutRecursion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAnEmptyBinaryTree_WhenTraversingPostOrderWithoutRecursion_ThenNoException() {
|
||||||
|
|
||||||
|
BinaryTree empty = new BinaryTree();
|
||||||
|
|
||||||
|
empty.traversePostOrderWithoutRecursion();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenABinaryTree_WhenTraversingLevelOrder_ThenPrintValues() {
|
public void givenABinaryTree_WhenTraversingLevelOrder_ThenPrintValues() {
|
||||||
|
|
||||||
|
@ -47,3 +47,4 @@ Available commands (assumes httpie - https://github.com/jkbrzt/httpie):
|
|||||||
## Relevant articles:
|
## Relevant articles:
|
||||||
|
|
||||||
- [Supercharge Java Authentication with JSON Web Tokens (JWTs)](https://www.baeldung.com/java-json-web-tokens-jjwt)
|
- [Supercharge Java Authentication with JSON Web Tokens (JWTs)](https://www.baeldung.com/java-json-web-tokens-jjwt)
|
||||||
|
- [Decode a JWT Token in Java](https://www.baeldung.com/java-jwt-token-decode)
|
||||||
|
@ -41,6 +41,12 @@
|
|||||||
<artifactId>jjwt</artifactId>
|
<artifactId>jjwt</artifactId>
|
||||||
<version>${jjwt.version}</version>
|
<version>${jjwt.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package io.jsonwebtoken.jjwtfun.util;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import io.jsonwebtoken.impl.crypto.DefaultJwtSignatureValidator;
|
||||||
|
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
import static io.jsonwebtoken.SignatureAlgorithm.HS256;
|
||||||
|
|
||||||
|
public class JWTDecoderUtil {
|
||||||
|
|
||||||
|
public static String decodeJWTToken(String token) {
|
||||||
|
Base64.Decoder decoder = Base64.getDecoder();
|
||||||
|
|
||||||
|
String[] chunks = token.split("\\.");
|
||||||
|
|
||||||
|
String header = new String(decoder.decode(chunks[0]));
|
||||||
|
String payload = new String(decoder.decode(chunks[1]));
|
||||||
|
|
||||||
|
return header + " " + payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String decodeJWTToken(String token, String secretKey) throws Exception {
|
||||||
|
Base64.Decoder decoder = Base64.getDecoder();
|
||||||
|
|
||||||
|
String[] chunks = token.split("\\.");
|
||||||
|
|
||||||
|
String header = new String(decoder.decode(chunks[0]));
|
||||||
|
String payload = new String(decoder.decode(chunks[1]));
|
||||||
|
|
||||||
|
String tokenWithoutSignature = chunks[0] + "." + chunks[1];
|
||||||
|
String signature = chunks[2];
|
||||||
|
|
||||||
|
SignatureAlgorithm sa = HS256;
|
||||||
|
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), sa.getJcaName());
|
||||||
|
|
||||||
|
DefaultJwtSignatureValidator validator = new DefaultJwtSignatureValidator(sa, secretKeySpec);
|
||||||
|
|
||||||
|
if (!validator.isValid(tokenWithoutSignature, signature)) {
|
||||||
|
throw new Exception("Could not verify JWT token integrity!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return header + " " + payload;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package io.jsonwebtoken.jjwtfun.util;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
|
class JWTDecoderUtilUnitTest {
|
||||||
|
|
||||||
|
private final static String SIMPLE_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJhZWxkdW5nIFVzZXIiLCJpYXQiOjE1MTYyMzkwMjJ9";
|
||||||
|
private final static String SIGNED_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJhZWxkdW5nIFVzZXIiLCJpYXQiOjE1MTYyMzkwMjJ9.qH7Zj_m3kY69kxhaQXTa-ivIpytKXXjZc1ZSmapZnGE";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenSimpleToken_whenDecoding_thenStringOfHeaderPayloadAreReturned() {
|
||||||
|
assertThat(JWTDecoderUtil.decodeJWTToken(SIMPLE_TOKEN))
|
||||||
|
.contains(SignatureAlgorithm.HS256.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenSignedToken_whenDecodingWithInvalidSecret_thenIntegrityIsNotValidated() {
|
||||||
|
assertThatThrownBy(() -> JWTDecoderUtil.decodeJWTToken(SIGNED_TOKEN, "BAD_SECRET"))
|
||||||
|
.hasMessage("Could not verify JWT token integrity!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenSignedToken_whenDecodingWithValidSecret_thenIntegrityIsValidated() throws Exception {
|
||||||
|
assertThat(JWTDecoderUtil.decodeJWTToken(SIGNED_TOKEN, "MySecretKey"))
|
||||||
|
.contains("Baeldung User");
|
||||||
|
}
|
||||||
|
}
|
@ -10,4 +10,8 @@ An easy way to check that everything is working as expected is issuing any *kube
|
|||||||
```shell
|
```shell
|
||||||
$ kubectl get nodes
|
$ kubectl get nodes
|
||||||
```
|
```
|
||||||
If you get a valid response, then you're good to go.
|
If you get a valid response, then you're good to go.
|
||||||
|
|
||||||
|
### Relevant Articles:
|
||||||
|
|
||||||
|
- [Paging and Async Calls with the Kubernetes API](https://www.baeldung.com/java-kubernetes-paging-async)
|
||||||
|
@ -16,6 +16,12 @@
|
|||||||
<artifactId>client-java</artifactId>
|
<artifactId>client-java</artifactId>
|
||||||
<version>11.0.0</version>
|
<version>11.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>1.2.3</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.baeldung.kubernetes.intro;
|
||||||
|
|
||||||
|
import io.kubernetes.client.openapi.ApiCallback;
|
||||||
|
import io.kubernetes.client.openapi.ApiException;
|
||||||
|
import io.kubernetes.client.openapi.apis.CoreV1Api;
|
||||||
|
import okhttp3.Call;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ApiInvoker<R> {
|
||||||
|
Call apply(CoreV1Api api, ApiCallback<R> callback) throws ApiException;
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package com.baeldung.kubernetes.intro;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import io.kubernetes.client.openapi.ApiCallback;
|
||||||
|
import io.kubernetes.client.openapi.ApiException;
|
||||||
|
import io.kubernetes.client.openapi.apis.CoreV1Api;
|
||||||
|
import okhttp3.Call;
|
||||||
|
|
||||||
|
public class AsyncHelper<R> implements ApiCallback<R> {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AsyncHelper.class);
|
||||||
|
|
||||||
|
private CoreV1Api api;
|
||||||
|
private CompletableFuture<R> callResult;
|
||||||
|
|
||||||
|
private AsyncHelper(CoreV1Api api) {
|
||||||
|
this.api = api;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> CompletableFuture<T> doAsync(CoreV1Api api, ApiInvoker<T> invoker) {
|
||||||
|
|
||||||
|
AsyncHelper<T> p = new AsyncHelper<>(api);
|
||||||
|
return p.execute(invoker);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompletableFuture<R> execute( ApiInvoker<R> invoker) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
callResult = new CompletableFuture<>();
|
||||||
|
log.info("[I38] Calling API...");
|
||||||
|
final Call call = invoker.apply(api,this);
|
||||||
|
log.info("[I41] API Succesfully invoked: method={}, url={}",
|
||||||
|
call.request().method(),
|
||||||
|
call.request().url());
|
||||||
|
return callResult;
|
||||||
|
}
|
||||||
|
catch(ApiException aex) {
|
||||||
|
callResult.completeExceptionally(aex);
|
||||||
|
return callResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(ApiException e, int statusCode, Map<String, List<String>> responseHeaders) {
|
||||||
|
log.error("[E53] onFailure",e);
|
||||||
|
callResult.completeExceptionally(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(R result, int statusCode, Map<String, List<String>> responseHeaders) {
|
||||||
|
log.error("[E61] onSuccess: statusCode={}",statusCode);
|
||||||
|
callResult.complete(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUploadProgress(long bytesWritten, long contentLength, boolean done) {
|
||||||
|
log.info("[E61] onUploadProgress: bytesWritten={}, contentLength={}, done={}",bytesWritten,contentLength,done);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDownloadProgress(long bytesRead, long contentLength, boolean done) {
|
||||||
|
log.info("[E75] onDownloadProgress: bytesRead={}, contentLength={}, done={}",bytesRead,contentLength,done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.baeldung.kubernetes.intro;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import io.kubernetes.client.openapi.ApiClient;
|
||||||
|
import io.kubernetes.client.openapi.apis.CoreV1Api;
|
||||||
|
import io.kubernetes.client.openapi.models.V1NodeList;
|
||||||
|
import io.kubernetes.client.util.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Philippe
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ListNodesAsync {
|
||||||
|
|
||||||
|
private static Logger log = LoggerFactory.getLogger(ListNodesAsync.class);
|
||||||
|
/**
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
// Initial setup
|
||||||
|
ApiClient client = Config.defaultClient();
|
||||||
|
CoreV1Api api = new CoreV1Api(client);
|
||||||
|
|
||||||
|
// Start async call
|
||||||
|
CompletableFuture<V1NodeList> p = AsyncHelper.doAsync(api,(capi,cb) ->
|
||||||
|
capi.listNodeAsync(null, null, null, null, null, null, null, null, 10, false, cb)
|
||||||
|
);
|
||||||
|
|
||||||
|
p.thenAcceptAsync((nodeList) -> {
|
||||||
|
log.info("[I40] Processing results...");
|
||||||
|
nodeList.getItems()
|
||||||
|
.stream()
|
||||||
|
.forEach((node) -> System.out.println(node.getMetadata()));
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info("[I46] Waiting results...");
|
||||||
|
p.get(10, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.baeldung.kubernetes.intro;
|
||||||
|
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import io.kubernetes.client.openapi.ApiClient;
|
||||||
|
import io.kubernetes.client.openapi.apis.CoreV1Api;
|
||||||
|
import io.kubernetes.client.openapi.models.V1NodeList;
|
||||||
|
import io.kubernetes.client.openapi.models.V1PodList;
|
||||||
|
import io.kubernetes.client.util.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Philippe
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ListPodsPaged {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ListPodsPaged.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
ApiClient client = Config.defaultClient();
|
||||||
|
CoreV1Api api = new CoreV1Api(client);
|
||||||
|
String continuationToken = null;
|
||||||
|
int limit = 2; // Just for illustration purposes. Real world values would range from ~100 to ~1000/page
|
||||||
|
Long remaining = null;
|
||||||
|
do {
|
||||||
|
log.info("==========================================================================");
|
||||||
|
log.info("Retrieving data: continuationToken={}, remaining={}", continuationToken,remaining);
|
||||||
|
V1PodList items = api.listPodForAllNamespaces(null, continuationToken, null, null, limit, null, null, null, 10, false);
|
||||||
|
continuationToken = items.getMetadata().getContinue();
|
||||||
|
remaining = items.getMetadata().getRemainingItemCount();
|
||||||
|
items.getItems()
|
||||||
|
.stream()
|
||||||
|
.forEach((node) -> System.out.println(node.getMetadata()));
|
||||||
|
} while( continuationToken != null );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.baeldung.kubernetes.intro;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class ListNodesAsyncLiveTest {
|
||||||
|
@Test
|
||||||
|
void whenListNodes_thenSuccess() throws Exception {
|
||||||
|
ListNodesAsync.main(new String[] {});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.baeldung.kubernetes.intro;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class ListPodsPagedLiveTest {
|
||||||
|
@Test
|
||||||
|
void whenListPodsPage_thenSuccess() throws Exception {
|
||||||
|
ListPodsPaged.main(new String[] {});
|
||||||
|
}
|
||||||
|
}
|
11
kubernetes/k8s-intro/src/test/resources/logback.xml
Normal file
11
kubernetes/k8s-intro/src/test/resources/logback.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<configuration>
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="debug">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
@ -82,7 +82,7 @@
|
|||||||
<rest-assured.version>3.3.0</rest-assured.version>
|
<rest-assured.version>3.3.0</rest-assured.version>
|
||||||
<!-- plugins -->
|
<!-- plugins -->
|
||||||
<thin.version>1.0.22.RELEASE</thin.version>
|
<thin.version>1.0.22.RELEASE</thin.version>
|
||||||
<spring-boot.version>2.4.0</spring-boot.version>
|
<spring-boot.version>2.4.3</spring-boot.version>
|
||||||
<aspectjweaver.version>1.9.1</aspectjweaver.version>
|
<aspectjweaver.version>1.9.1</aspectjweaver.version>
|
||||||
<!-- this property can be removed once we update Mockito version in the main pom.xml -->
|
<!-- this property can be removed once we update Mockito version in the main pom.xml -->
|
||||||
<mockito.version>3.4.0</mockito.version>
|
<mockito.version>3.4.0</mockito.version>
|
||||||
|
@ -38,8 +38,8 @@ public class UsingOptional {
|
|||||||
.flatMap(list -> list.stream().findFirst());
|
.flatMap(list -> list.stream().findFirst());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<List> getOptionalList() {
|
private Optional<List<String>> getOptionalList() {
|
||||||
return Optional.ofNullable(getList());
|
return Optional.of(getList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String doSomething(boolean processed) {
|
private String doSomething(boolean processed) {
|
||||||
|
@ -19,22 +19,22 @@ class UsingOptionalUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenArgIsFalse_thenReturnEmptyResponse() {
|
void whenArgIsFalse_thenReturnEmptyResponse() {
|
||||||
Optional<Object> result = dataObject.process(false);
|
Optional<Object> result = dataObject.process(false);
|
||||||
|
|
||||||
assertFalse(result.isPresent());
|
assertFalse(result.isPresent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenArgIsTrue_thenReturnValidResponse() {
|
void whenArgIsTrue_thenReturnValidResponse() {
|
||||||
Optional<Object> result = dataObject.process(true);
|
Optional<Object> result = dataObject.process(true);
|
||||||
|
|
||||||
assertTrue(result.isPresent());
|
assertTrue(result.isPresent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenArgIsFalse_thenChainResponseAndThrowException() {
|
void whenArgIsFalse_thenChainResponseAndThrowException() {
|
||||||
assertThrows(Exception.class, () -> dataObject.process(false).orElseThrow(() -> new Exception()));
|
assertThrows(Exception.class, () -> dataObject.process(false).orElseThrow(Exception::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test()
|
@Test()
|
||||||
@ -51,7 +51,4 @@ class UsingOptionalUnitTest {
|
|||||||
void whenOptionalListFirst_returnsEmptyOptional() {
|
void whenOptionalListFirst_returnsEmptyOptional() {
|
||||||
assertFalse(dataObject.optionalListFirst().isPresent());
|
assertFalse(dataObject.optionalListFirst().isPresent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.baeldung.tableexists;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
class DatabaseConfig {
|
||||||
|
static Connection connect() throws ClassNotFoundException, SQLException {
|
||||||
|
Class.forName("org.h2.Driver");
|
||||||
|
String url = "jdbc:h2:mem:testdb";
|
||||||
|
return DriverManager.getConnection(url, "user", "password");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createTables(Connection connection) throws SQLException {
|
||||||
|
connection.createStatement().executeUpdate("create table EMPLOYEE (id int primary key auto_increment, name VARCHAR(255))");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dropTables(Connection connection) throws SQLException {
|
||||||
|
connection.createStatement().executeUpdate("drop table EMPLOYEE");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.baeldung.tableexists;
|
||||||
|
|
||||||
|
import java.sql.*;
|
||||||
|
|
||||||
|
class TableChecker {
|
||||||
|
static void printAllTables(Connection connection, String tableName) throws SQLException {
|
||||||
|
DatabaseMetaData databaseMetaData = connection.getMetaData();
|
||||||
|
ResultSet resultSet = databaseMetaData.getTables(null, null, tableName, new String[] {"TABLE"});
|
||||||
|
|
||||||
|
while (resultSet.next()) {
|
||||||
|
String name = resultSet.getString("TABLE_NAME");
|
||||||
|
String schema = resultSet.getString("TABLE_SCHEM");
|
||||||
|
System.out.println(name + " on schema " + schema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean tableExists(Connection connection, String tableName) throws SQLException {
|
||||||
|
DatabaseMetaData meta = connection.getMetaData();
|
||||||
|
ResultSet resultSet = meta.getTables(null, null, tableName, new String[] {"TABLE"});
|
||||||
|
|
||||||
|
return resultSet.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean tableExistsSQL(Connection connection, String tableName) throws SQLException {
|
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement("SELECT count(*) " +
|
||||||
|
"FROM information_schema.tables " +
|
||||||
|
"WHERE table_name = ?" +
|
||||||
|
"LIMIT 1;");
|
||||||
|
preparedStatement.setString(1, tableName);
|
||||||
|
|
||||||
|
ResultSet resultSet = preparedStatement.executeQuery();
|
||||||
|
resultSet.next();
|
||||||
|
return resultSet.getInt(1) != 0;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
package com.baeldung.tableexists;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
class TableCheckerUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenCreatedTable_shouldFindTable() throws SQLException, ClassNotFoundException {
|
||||||
|
// given
|
||||||
|
Connection connection = DatabaseConfig.connect();
|
||||||
|
DatabaseConfig.createTables(connection);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean tableExists = TableChecker.tableExists(connection, "EMPLOYEE");
|
||||||
|
|
||||||
|
// then
|
||||||
|
TableChecker.printAllTables(connection, null);
|
||||||
|
assertTrue(tableExists);
|
||||||
|
|
||||||
|
DatabaseConfig.dropTables(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenCreatedTable_shouldFindTableWithSQL() throws SQLException, ClassNotFoundException {
|
||||||
|
// given
|
||||||
|
Connection connection = DatabaseConfig.connect();
|
||||||
|
DatabaseConfig.createTables(connection);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean tableExists = TableChecker.tableExistsSQL(connection, "EMPLOYEE");
|
||||||
|
|
||||||
|
// then
|
||||||
|
TableChecker.printAllTables(connection, null);
|
||||||
|
assertTrue(tableExists);
|
||||||
|
|
||||||
|
DatabaseConfig.dropTables(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenNoTable_shouldNotFindTable() throws SQLException, ClassNotFoundException {
|
||||||
|
// given
|
||||||
|
Connection connection = DatabaseConfig.connect();
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean tableExists = TableChecker.tableExists(connection, "EMPLOYEE");
|
||||||
|
|
||||||
|
// then
|
||||||
|
TableChecker.printAllTables(connection, null);
|
||||||
|
assertFalse(tableExists);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenNoTable_shouldNotFindTableWithSQL() throws SQLException, ClassNotFoundException {
|
||||||
|
// given
|
||||||
|
Connection connection = DatabaseConfig.connect();
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean tableExists = TableChecker.tableExistsSQL(connection, "EMPLOYEE");
|
||||||
|
|
||||||
|
// then
|
||||||
|
TableChecker.printAllTables(connection, null);
|
||||||
|
assertFalse(tableExists);
|
||||||
|
}
|
||||||
|
}
|
@ -162,6 +162,25 @@ public class ApplicationView {
|
|||||||
return betweenItems;
|
return betweenItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To get records having itemName in 'Skate Board', 'Paint' and 'Glue'
|
||||||
|
public String[] inCriteria() {
|
||||||
|
final Session session = HibernateUtil.getHibernateSession();
|
||||||
|
final CriteriaBuilder cb = session.getCriteriaBuilder();
|
||||||
|
final CriteriaQuery<Item> cr = cb.createQuery(Item.class);
|
||||||
|
final Root<Item> root = cr.from(Item.class);
|
||||||
|
cr.select(root)
|
||||||
|
.where(root.get("itemName").in("Skate Board", "Paint", "Glue"));
|
||||||
|
Query<Item> query = session.createQuery(cr);
|
||||||
|
final List<Item> inItemsList = query.getResultList();
|
||||||
|
final String inItems[] = new String[inItemsList.size()];
|
||||||
|
for (int i = 0; i < inItemsList.size(); i++) {
|
||||||
|
inItems[i] = inItemsList.get(i)
|
||||||
|
.getItemName();
|
||||||
|
}
|
||||||
|
session.close();
|
||||||
|
return inItems;
|
||||||
|
}
|
||||||
|
|
||||||
// To check if the given property is null
|
// To check if the given property is null
|
||||||
public String[] nullCriteria() {
|
public String[] nullCriteria() {
|
||||||
final Session session = HibernateUtil.getHibernateSession();
|
final Session session = HibernateUtil.getHibernateSession();
|
||||||
|
@ -189,6 +189,18 @@ public class HibernateCriteriaIntegrationTest {
|
|||||||
assertArrayEquals(expectedPriceBetweenItems, av.betweenCriteria());
|
assertArrayEquals(expectedPriceBetweenItems, av.betweenCriteria());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void inCriteriaQuery() {
|
||||||
|
final Session session = HibernateUtil.getHibernateSession();
|
||||||
|
final List<Item> expectedInList = session.createQuery("From Item where itemName in ('Skate Board', 'Paint', 'Glue')").list();
|
||||||
|
final String expectedNameInItems[] = new String[expectedInList.size()];
|
||||||
|
for (int i = 0; i < expectedInList.size(); i++) {
|
||||||
|
expectedNameInItems[i] = expectedInList.get(i).getItemName();
|
||||||
|
}
|
||||||
|
session.close();
|
||||||
|
assertArrayEquals(expectedNameInItems, av.inCriteria());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenNewItemPrice_whenCriteriaUpdate_thenReturnAffectedResult() {
|
public void givenNewItemPrice_whenCriteriaUpdate_thenReturnAffectedResult() {
|
||||||
|
|
||||||
|
2
pom.xml
2
pom.xml
@ -1370,7 +1370,7 @@
|
|||||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<log4j.version>1.2.17</log4j.version>
|
<log4j.version>1.2.17</log4j.version>
|
||||||
<esapi.version>2.1.0.1</esapi.version>
|
<esapi.version>2.2.2.0</esapi.version>
|
||||||
<jmh-core.version>1.19</jmh-core.version>
|
<jmh-core.version>1.19</jmh-core.version>
|
||||||
<jmh-generator.version>1.19</jmh-generator.version>
|
<jmh-generator.version>1.19</jmh-generator.version>
|
||||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||||
|
@ -174,7 +174,7 @@
|
|||||||
<jsonb-api.version>1.0</jsonb-api.version>
|
<jsonb-api.version>1.0</jsonb-api.version>
|
||||||
<geronimo-json_1.1_spec.version>1.0</geronimo-json_1.1_spec.version>
|
<geronimo-json_1.1_spec.version>1.0</geronimo-json_1.1_spec.version>
|
||||||
<commons-collections4.version>4.1</commons-collections4.version>
|
<commons-collections4.version>4.1</commons-collections4.version>
|
||||||
<jetty-reactive-httpclient.version>1.0.3</jetty-reactive-httpclient.version>
|
<jetty-reactive-httpclient.version>1.1.6</jetty-reactive-httpclient.version>
|
||||||
<okhttp.version>4.0.1</okhttp.version>
|
<okhttp.version>4.0.1</okhttp.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
@ -2,3 +2,4 @@
|
|||||||
|
|
||||||
- [Spring Boot: Customize the Jackson ObjectMapper](https://www.baeldung.com/spring-boot-customize-jackson-objectmapper)
|
- [Spring Boot: Customize the Jackson ObjectMapper](https://www.baeldung.com/spring-boot-customize-jackson-objectmapper)
|
||||||
- [“HttpMessageNotWritableException: No converter found for return value of type”](https://www.baeldung.com/spring-no-converter-found)
|
- [“HttpMessageNotWritableException: No converter found for return value of type”](https://www.baeldung.com/spring-no-converter-found)
|
||||||
|
- [Creating a Read-Only Repository with Spring Data](https://www.baeldung.com/spring-data-read-only-repository)
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.baeldung.boot.readonlyrepository;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Book
|
||||||
|
{
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
private String author;
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(String author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.baeldung.boot.readonlyrepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface BookReadOnlyRepository extends ReadOnlyRepository<Book, Long> {
|
||||||
|
|
||||||
|
List<Book> findByAuthor(String author);
|
||||||
|
|
||||||
|
List<Book> findByTitle(String title);
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.baeldung.boot.readonlyrepository;
|
||||||
|
|
||||||
|
import org.springframework.data.repository.NoRepositoryBean;
|
||||||
|
import org.springframework.data.repository.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@NoRepositoryBean
|
||||||
|
public interface ReadOnlyRepository<T, ID> extends Repository<T, ID> {
|
||||||
|
|
||||||
|
Optional<T> findById(ID id);
|
||||||
|
|
||||||
|
List<T> findAll();
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.baeldung.boot.readonlyrepository;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class ReadOnlyRepositoryApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(ReadOnlyRepositoryApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.baeldung.boot.readonlyrepository;
|
||||||
|
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
|
||||||
|
public interface BookRepository extends BookReadOnlyRepository, CrudRepository<Book, Long> {
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.baeldung.boot.readonlyrepository;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
@SpringBootTest( classes = ReadOnlyRepositoryApplication.class )
|
||||||
|
public class ReadOnlyRepositoryUnitTest
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private BookRepository bookRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BookReadOnlyRepository bookReadOnlyRepository;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenBooks_whenUsingReadOnlyRepository_thenGetThem() {
|
||||||
|
Book aChristmasCarolCharlesDickens = new Book();
|
||||||
|
aChristmasCarolCharlesDickens.setTitle("A Christmas Carol");
|
||||||
|
aChristmasCarolCharlesDickens.setAuthor("Charles Dickens");
|
||||||
|
bookRepository.save(aChristmasCarolCharlesDickens);
|
||||||
|
|
||||||
|
Book greatExpectationsCharlesDickens = new Book();
|
||||||
|
greatExpectationsCharlesDickens.setTitle("Great Expectations");
|
||||||
|
greatExpectationsCharlesDickens.setAuthor("Charles Dickens");
|
||||||
|
bookRepository.save(greatExpectationsCharlesDickens);
|
||||||
|
|
||||||
|
Book greatExpectationsKathyAcker = new Book();
|
||||||
|
greatExpectationsKathyAcker.setTitle("Great Expectations");
|
||||||
|
greatExpectationsKathyAcker.setAuthor("Kathy Acker");
|
||||||
|
bookRepository.save(greatExpectationsKathyAcker);
|
||||||
|
|
||||||
|
List<Book> charlesDickensBooks = bookReadOnlyRepository.findByAuthor("Charles Dickens");
|
||||||
|
Assertions.assertEquals(2, charlesDickensBooks.size());
|
||||||
|
|
||||||
|
List<Book> greatExpectationsBooks = bookReadOnlyRepository.findByTitle("Great Expectations");
|
||||||
|
Assertions.assertEquals(2, greatExpectationsBooks.size());
|
||||||
|
|
||||||
|
List<Book> allBooks = bookReadOnlyRepository.findAll();
|
||||||
|
Assertions.assertEquals(3, allBooks.size());
|
||||||
|
|
||||||
|
Long bookId = allBooks.get(0).getId();
|
||||||
|
Book book = bookReadOnlyRepository.findById(bookId).orElseThrow(NoSuchElementException::new);
|
||||||
|
Assertions.assertNotNull(book);
|
||||||
|
}
|
||||||
|
}
|
@ -84,12 +84,6 @@
|
|||||||
<version>${jquery.version}</version>
|
<version>${jquery.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-context</artifactId>
|
|
||||||
<version>${springcloud.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
<artifactId>httpclient</artifactId>
|
<artifactId>httpclient</artifactId>
|
||||||
@ -195,9 +189,7 @@
|
|||||||
<jpa.version>2.2</jpa.version>
|
<jpa.version>2.2</jpa.version>
|
||||||
<guava.version>18.0</guava.version>
|
<guava.version>18.0</guava.version>
|
||||||
<subethasmtp.version>3.1.7</subethasmtp.version>
|
<subethasmtp.version>3.1.7</subethasmtp.version>
|
||||||
<springcloud.version>2.0.2.RELEASE</springcloud.version>
|
|
||||||
<httpclient.version>4.5.8</httpclient.version>
|
<httpclient.version>4.5.8</httpclient.version>
|
||||||
<spring-boot.version>2.3.3.RELEASE</spring-boot.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,34 +1,35 @@
|
|||||||
package com.baeldung.charencoding.controller;
|
package com.baeldung.charencoding.controller;
|
||||||
|
|
||||||
import static org.mockito.Mockito.mock;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.mockito.Mockito.verify;
|
import org.springframework.mock.web.MockFilterChain;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import java.io.IOException;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
import org.springframework.web.filter.CharacterEncodingFilter;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import org.springframework.web.filter.CharacterEncodingFilter;
|
|
||||||
|
|
||||||
class CharEncodingCheckControllerUnitTest {
|
class CharEncodingCheckControllerUnitTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void whenCharEncodingFilter_thenVerifyEncoding() throws ServletException, IOException {
|
void whenCharEncodingFilter_thenVerifyEncoding() throws ServletException, IOException {
|
||||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
HttpServletRequest request = new MockHttpServletRequest();
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = new MockHttpServletResponse();
|
||||||
FilterChain chain = mock(FilterChain.class);
|
FilterChain chain = new MockFilterChain();
|
||||||
|
|
||||||
CharacterEncodingFilter filter = new CharacterEncodingFilter();
|
CharacterEncodingFilter filter = new CharacterEncodingFilter();
|
||||||
filter.setEncoding("UTF-8");
|
filter.setEncoding("UTF-8");
|
||||||
filter.setForceEncoding(true);
|
filter.setForceEncoding(true);
|
||||||
|
|
||||||
filter.doFilter(request, response, chain);
|
filter.doFilter(request, response, chain);
|
||||||
|
|
||||||
verify(request).setCharacterEncoding("UTF-8");
|
assertEquals("UTF-8", request.getCharacterEncoding());
|
||||||
verify(response).setCharacterEncoding("UTF-8");
|
assertEquals("UTF-8", response.getCharacterEncoding());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.baeldung.boot.properties.multidocument;
|
|||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
@ -21,6 +22,7 @@ public class StagingMultidocumentFilesIntegrationTest {
|
|||||||
private String baelRootProperty;
|
private String baelRootProperty;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("Fix and update https://www.baeldung.com/spring-boot-yaml-vs-properties article")
|
||||||
public void givenProductionProfileActive_whenApplicationStarts_thenDefaultPropertiesUser() {
|
public void givenProductionProfileActive_whenApplicationStarts_thenDefaultPropertiesUser() {
|
||||||
assertThat(baelCustomProperty).isEqualTo("stagingValue");
|
assertThat(baelCustomProperty).isEqualTo("stagingValue");
|
||||||
assertThat(baelRootProperty).isEqualTo("defaultRootLevelValue");
|
assertThat(baelRootProperty).isEqualTo("defaultRootLevelValue");
|
||||||
|
3
spring-boot-rest-2/README.md
Normal file
3
spring-boot-rest-2/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
### Relevant Article:
|
||||||
|
|
||||||
|
- [Get All Endpoints in Spring Boot](https://www.baeldung.com/spring-boot-get-all-endpoints)
|
44
spring-boot-rest-2/pom.xml
Normal file
44
spring-boot-rest-2/pom.xml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?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>com.baeldung.web</groupId>
|
||||||
|
<artifactId>spring-boot-rest-2</artifactId>
|
||||||
|
<name>spring-boot-rest-2</name>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
<description>Spring Boot Rest Module</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-boot-2</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../parent-boot-2</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.springfox</groupId>
|
||||||
|
<artifactId>springfox-boot-starter</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.baeldung.endpoint;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class SpringBootRestApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SpringBootRestApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.baeldung.endpoint.controller;
|
||||||
|
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class HelloController {
|
||||||
|
|
||||||
|
@GetMapping("/hello")
|
||||||
|
public ResponseEntity<String> hello() {
|
||||||
|
return ResponseEntity.ok("hello baeldung");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.baeldung.endpoint.listener;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class AnnotationDrivenEndpointsListener {
|
||||||
|
private final Logger LOGGER = LoggerFactory.getLogger("AnnotationDrivenEndpointsListener.class");
|
||||||
|
|
||||||
|
@EventListener
|
||||||
|
public void handleContextRefresh(ContextRefreshedEvent event) {
|
||||||
|
ApplicationContext applicationContext = event.getApplicationContext();
|
||||||
|
RequestMappingHandlerMapping requestMappingHandlerMapping = applicationContext
|
||||||
|
.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
|
||||||
|
Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping.getHandlerMethods();
|
||||||
|
map.forEach((key, value) -> LOGGER.info("{} {}", key, value));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.baeldung.endpoint.listener;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class EndpointsListener implements ApplicationListener<ContextRefreshedEvent> {
|
||||||
|
private final Logger LOGGER = LoggerFactory.getLogger("EndpointsListener.class");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||||
|
ApplicationContext applicationContext = event.getApplicationContext();
|
||||||
|
RequestMappingHandlerMapping requestMappingHandlerMapping = applicationContext
|
||||||
|
.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
|
||||||
|
Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping.getHandlerMethods();
|
||||||
|
map.forEach((key, value) -> LOGGER.info("{} {}", key, value));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.baeldung.endpoint.swagger;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import springfox.documentation.builders.PathSelectors;
|
||||||
|
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
|
import springfox.documentation.spi.DocumentationType;
|
||||||
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class SpringFoxConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Docket api() {
|
||||||
|
return new Docket(DocumentationType.SWAGGER_2)
|
||||||
|
.select()
|
||||||
|
.apis(RequestHandlerSelectors.any())
|
||||||
|
.paths(PathSelectors.any())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
management.endpoints.web.exposure.include=mappings
|
@ -79,7 +79,6 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-commons</artifactId>
|
<artifactId>spring-data-commons</artifactId>
|
||||||
<version>2.3.0.RELEASE</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -38,6 +38,11 @@
|
|||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
|
||||||
|
<version>${spring-cloud-netflix-zuul.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
@ -46,10 +51,6 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
@ -79,8 +80,8 @@
|
|||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<spring-cloud.version>Hoxton.SR4</spring-cloud.version>
|
<spring-cloud.version>2020.0.0</spring-cloud.version>
|
||||||
<spring-boot.version>2.3.3.RELEASE</spring-boot.version>
|
<spring-cloud-netflix-zuul.version>2.2.2.RELEASE</spring-cloud-netflix-zuul.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
<artifactId>spring-cloud-zuul-ratelimit</artifactId>
|
<artifactId>spring-cloud-zuul-ratelimit</artifactId>
|
||||||
<version>${rate.limit.version}</version>
|
<version>${rate.limit.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
@ -13,6 +13,10 @@
|
|||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
package com.baeldung.scheduling.dynamic;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
import org.springframework.scheduling.annotation.SchedulingConfigurer;
|
||||||
|
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ComponentScan("com.baeldung.scheduling.dynamic")
|
||||||
|
@EnableScheduling
|
||||||
|
public class DynamicSchedulingConfig implements SchedulingConfigurer {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TickService tickService;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Executor taskExecutor() {
|
||||||
|
return Executors.newSingleThreadScheduledExecutor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
|
||||||
|
taskRegistrar.setScheduler(taskExecutor());
|
||||||
|
taskRegistrar.addTriggerTask(
|
||||||
|
() -> tickService.tick(),
|
||||||
|
context -> {
|
||||||
|
Optional<Date> lastCompletionTime =
|
||||||
|
Optional.ofNullable(context.lastCompletionTime());
|
||||||
|
Instant nextExecutionTime =
|
||||||
|
lastCompletionTime.orElseGet(Date::new).toInstant()
|
||||||
|
.plusMillis(tickService.getDelay());
|
||||||
|
return Date.from(nextExecutionTime);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.baeldung.scheduling.dynamic;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TickService {
|
||||||
|
|
||||||
|
private long delay = 0;
|
||||||
|
|
||||||
|
public long getDelay() {
|
||||||
|
this.delay += 1000;
|
||||||
|
System.out.println("delaying " + this.delay + " milliseconds...");
|
||||||
|
return this.delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick() {
|
||||||
|
final long now = System.currentTimeMillis() / 1000;
|
||||||
|
System.out
|
||||||
|
.println("schedule tasks with dynamic delay - " + now);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.baeldung.scheduling;
|
||||||
|
|
||||||
|
import com.baeldung.scheduling.dynamic.DynamicSchedulingConfig;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||||
|
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration(classes = {
|
||||||
|
DynamicSchedulingConfig.class}, loader = AnnotationConfigContextLoader.class)
|
||||||
|
public class DynamicSchedulingIntegrationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTickServiceTick() throws InterruptedException {
|
||||||
|
Thread.sleep(6000);
|
||||||
|
}
|
||||||
|
}
|
@ -49,7 +49,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.owasp.esapi</groupId>
|
<groupId>org.owasp.esapi</groupId>
|
||||||
<artifactId>esapi</artifactId>
|
<artifactId>esapi</artifactId>
|
||||||
<version>2.2.2.0</version>
|
<version>${esapi.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jsoup</groupId>
|
<groupId>org.jsoup</groupId>
|
||||||
|
@ -6,4 +6,4 @@
|
|||||||
- [A Quick Guide to Spring MVC Matrix Variables](https://www.baeldung.com/spring-mvc-matrix-variables)
|
- [A Quick Guide to Spring MVC Matrix Variables](https://www.baeldung.com/spring-mvc-matrix-variables)
|
||||||
- [Converting a Spring MultipartFile to a File](https://www.baeldung.com/spring-multipartfile-to-file)
|
- [Converting a Spring MultipartFile to a File](https://www.baeldung.com/spring-multipartfile-to-file)
|
||||||
- [Testing a Spring Multipart POST Request](https://www.baeldung.com/spring-multipart-post-request-test)
|
- [Testing a Spring Multipart POST Request](https://www.baeldung.com/spring-multipart-post-request-test)
|
||||||
- [Spring @Pathvariable Annotation](https://www.baeldung.com/spring-pathvariable)
|
- [Spring @PathVariable Annotation](https://www.baeldung.com/spring-pathvariable)
|
||||||
|
4
testing-modules/mockito-3/.gitignore
vendored
Normal file
4
testing-modules/mockito-3/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/target/
|
||||||
|
/.settings/
|
||||||
|
/.classpath
|
||||||
|
/.project
|
38
testing-modules/mockito-3/pom.xml
Normal file
38
testing-modules/mockito-3/pom.xml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?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>mockito-3</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>mockito-3</name>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../../</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-inline</artifactId>
|
||||||
|
<version>${mockito.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<version>${assertj.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<mockito.version>3.8.0</mockito.version>
|
||||||
|
<assertj.version>3.8.0</assertj.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.baeldung.mockito.mockedstatic;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class StaticUtils {
|
||||||
|
|
||||||
|
private StaticUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> range(int start, int end) {
|
||||||
|
return IntStream.range(start, end)
|
||||||
|
.boxed()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String name() {
|
||||||
|
return "Baeldung";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
testing-modules/mockito-3/src/main/resources/logback.xml
Normal file
13
testing-modules/mockito-3/src/main/resources/logback.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||||
|
</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.baeldung.mockito.mockedstatic;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.MockedStatic;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
class MockedStaticUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenStaticMethodWithNoArgs_whenMocked_thenReturnsMockSuccessfully() {
|
||||||
|
assertThat(StaticUtils.name()).isEqualTo("Baeldung");
|
||||||
|
|
||||||
|
try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) {
|
||||||
|
utilities.when(StaticUtils::name).thenReturn("Eugen");
|
||||||
|
assertThat(StaticUtils.name()).isEqualTo("Eugen");
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(StaticUtils.name()).isEqualTo("Baeldung");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenStaticMethodWithArgs_whenMocked_thenReturnsMockSuccessfully() {
|
||||||
|
assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);
|
||||||
|
|
||||||
|
try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) {
|
||||||
|
utilities.when(() -> StaticUtils.range(2, 6))
|
||||||
|
.thenReturn(Arrays.asList(10, 11, 12));
|
||||||
|
|
||||||
|
assertThat(StaticUtils.range(2, 6)).containsExactly(10, 11, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,7 +23,8 @@
|
|||||||
<module>junit5-migration</module>
|
<module>junit5-migration</module>
|
||||||
<module>load-testing-comparison</module>
|
<module>load-testing-comparison</module>
|
||||||
<module>mockito</module>
|
<module>mockito</module>
|
||||||
<module>mockito-2</module>
|
<module>mockito-2</module>
|
||||||
|
<module>mockito-3</module>
|
||||||
<module>hamcrest</module>
|
<module>hamcrest</module>
|
||||||
<module>mocks</module>
|
<module>mocks</module>
|
||||||
<module>mockserver</module>
|
<module>mockserver</module>
|
||||||
|
@ -125,7 +125,7 @@
|
|||||||
<awaitility.version>3.1.6</awaitility.version>
|
<awaitility.version>3.1.6</awaitility.version>
|
||||||
<junit.jupiter.version>5.7.0</junit.jupiter.version>
|
<junit.jupiter.version>5.7.0</junit.jupiter.version>
|
||||||
<junit.commons.version>1.7.0</junit.commons.version>
|
<junit.commons.version>1.7.0</junit.commons.version>
|
||||||
<spring.version>5.3.0</spring.version>
|
<spring.version>5.3.4</spring.version>
|
||||||
<javax.servlet-api.version>4.0.1</javax.servlet-api.version>
|
<javax.servlet-api.version>4.0.1</javax.servlet-api.version>
|
||||||
<javax.persistence.version>2.1.1</javax.persistence.version>
|
<javax.persistence.version>2.1.1</javax.persistence.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
package com.baeldung.overrideproperties;
|
package com.baeldung.overrideproperties;
|
||||||
|
|
||||||
import com.baeldung.overrideproperties.resolver.PropertySourceResolver;
|
import com.baeldung.overrideproperties.resolver.PropertySourceResolver;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
@SpringBootTest
|
||||||
@ContextConfiguration(initializers = PropertyOverrideContextInitializer.class, classes = Application.class)
|
@ContextConfiguration(initializers = PropertyOverrideContextInitializer.class, classes = Application.class)
|
||||||
public class ContextPropertySourceResolverIntegrationTest {
|
public class ContextPropertySourceResolverIntegrationTest {
|
||||||
|
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
package com.baeldung.overrideproperties;
|
package com.baeldung.overrideproperties;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
|
||||||
import com.baeldung.overrideproperties.resolver.PropertySourceResolver;
|
import com.baeldung.overrideproperties.resolver.PropertySourceResolver;
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
@ActiveProfiles("test")
|
@ActiveProfiles("test")
|
||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
|
@ -12,6 +12,6 @@ public class PropertyOverrideContextInitializer implements ApplicationContextIni
|
|||||||
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
|
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
|
||||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext, "example.firstProperty=" + PROPERTY_FIRST_VALUE);
|
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext, "example.firstProperty=" + PROPERTY_FIRST_VALUE);
|
||||||
|
|
||||||
TestPropertySourceUtils.addPropertiesFilesToEnvironment(configurableApplicationContext, "context-override-application.properties");
|
TestPropertySourceUtils.addPropertiesFilesToEnvironment(configurableApplicationContext, "classpath:context-override-application.properties");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
package com.baeldung.overrideproperties;
|
package com.baeldung.overrideproperties;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
|
||||||
import com.baeldung.overrideproperties.resolver.PropertySourceResolver;
|
import com.baeldung.overrideproperties.resolver.PropertySourceResolver;
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
@SpringBootTest(properties = { "example.firstProperty=annotation" })
|
@SpringBootTest(properties = { "example.firstProperty=annotation" })
|
||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
public class SpringBootPropertySourceResolverIntegrationTest {
|
public class SpringBootPropertySourceResolverIntegrationTest {
|
||||||
@ -23,8 +23,8 @@ public class SpringBootPropertySourceResolverIntegrationTest {
|
|||||||
final String firstProperty = propertySourceResolver.getFirstProperty();
|
final String firstProperty = propertySourceResolver.getFirstProperty();
|
||||||
final String secondProperty = propertySourceResolver.getSecondProperty();
|
final String secondProperty = propertySourceResolver.getSecondProperty();
|
||||||
|
|
||||||
Assert.assertEquals("annotation", firstProperty);
|
assertEquals("annotation", firstProperty);
|
||||||
Assert.assertEquals("file", secondProperty);
|
assertEquals("file", secondProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,17 +1,16 @@
|
|||||||
package com.baeldung.overrideproperties;
|
package com.baeldung.overrideproperties;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
|
||||||
import com.baeldung.overrideproperties.resolver.PropertySourceResolver;
|
import com.baeldung.overrideproperties.resolver.PropertySourceResolver;
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
public class TestResourcePropertySourceResolverIntegrationTest {
|
public class TestResourcePropertySourceResolverIntegrationTest {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user