Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Amit Bhave 2021-03-21 18:51:04 +05:30
commit f7b8d67c0b
297 changed files with 6297 additions and 454 deletions
algorithms-miscellaneous-5/src
main/java/com/baeldung/algorithms/maximumsubarray
test/java/com/baeldung/algorithms/maximumsubarray
apache-poi
README.md
src/test/java/com/baeldung/poi/excel/insert
core-java-modules
core-java-10
README.md
src/test/java/com/baeldung/java10/streams
core-java-12
core-java-13
core-java-14
core-java-9-new-features
core-java-annotations/src
main/java/com/baeldung/annotations
test/java/com/baeldung/annotations
core-java-char
core-java-collections-4
README.mdpom.xml
src
main/java/com/baeldung/collections/dequestack
test/java/com/baeldung/collections/dequestack
core-java-collections-list-3/src/main/java/com/baeldung/list/primitive
core-java-collections-maps-3
README.mdpom.xml
src
main/java/com/baeldung/map/propertieshashmap
test
java/com/baeldung/map
resources
core-java-concurrency-collections/src/test/java/com/baeldung/java/stream
core-java-io-conversions/src/test/java/com/baeldung/filetoinputstream
core-java-jpms/decoupling-pattern2/consumermodule
core-java-jvm
core-java-lang-3
core-java-lang-4
core-java-lang-math-3
core-java-lang-oop-generics
README.md
src
main/java/com/baeldung/uncheckedcast
test/java/com/baeldung/uncheckedcast
core-java-lang-oop-types/src
main/java/com/baeldung/classfile
test/java/com/baeldung/classfile
core-java-nio-2
pom.xml
src/test/java/com/baeldung/selector
core-java-reflection-2
README.mdpom.xml
src
main/java/com/baeldung/reflection/access/privatemethods
test/java/com/baeldung/reflection/access/privatemethods
core-java-security-2
pom.xml
data-structures/src
main/java/com/baeldung
circularbuffer
circularlinkedlist
test/java/com/baeldung/circularlinkedlist
docker
README.md
heap-sizing
Dockerfilepom.xml
src/main/java/com/baeldung/docker/heapsizing
guest/core-kotlin
jackson-modules/jackson-annotations/src
main/java/com/baeldung/jackson/bidirection
test/java/com/baeldung/jackson/bidirection
java-collections-maps-3
java-rmi/src/test/java/com/baeldung/rmi
jjwt
README.mdpom.xml
src
main/java/io/jsonwebtoken/jjwtfun/util
test/java/io/jsonwebtoken/jjwtfun/util
jmeter
README.md
src
main
test/java/com/baeldung
kubernetes
libraries-http-2
maven-modules/maven-plugins/jaxws

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

@ -11,3 +11,4 @@ This module contains articles about Apache POI
- [Get String Value of Excel Cell with Apache POI](https://www.baeldung.com/java-apache-poi-cell-string-value) - [Get String Value of Excel Cell with Apache POI](https://www.baeldung.com/java-apache-poi-cell-string-value)
- [Read Excel Cell Value Rather Than Formula With Apache POI](https://www.baeldung.com/apache-poi-read-cell-value-formula) - [Read Excel Cell Value Rather Than Formula With Apache POI](https://www.baeldung.com/apache-poi-read-cell-value-formula)
- [Setting Formulas in Excel with Apache POI](https://www.baeldung.com/java-apache-poi-set-formulas) - [Setting Formulas in Excel with Apache POI](https://www.baeldung.com/java-apache-poi-set-formulas)
- [Insert a Row in Excel Using Apache POI](https://www.baeldung.com/apache-poi-insert-excel-row)

@ -0,0 +1,50 @@
package com.baeldung.poi.excel.insert;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Paths;
public class ExcelInsertRowUnitTest {
private static final String FILE_NAME = "test.xlsx";
private static final String NEW_FILE_NAME = "new_test.xlsx";
private String fileLocation;
@Before
public void setup() throws URISyntaxException {
fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME).toURI()).toString();
}
@Test
public void givenWorkbook_whenInsertRowBetween_thenRowCreated() throws IOException {
int startRow = 2;
int rowNumber = 1;
Workbook workbook = new XSSFWorkbook(fileLocation);
Sheet sheet = workbook.getSheetAt(0);
int lastRow = sheet.getLastRowNum();
if (lastRow < startRow) {
sheet.createRow(startRow);
}
sheet.shiftRows(startRow, lastRow, rowNumber, true, true);
sheet.createRow(startRow);
FileOutputStream outputStream = new FileOutputStream(NEW_FILE_NAME);
workbook.write(outputStream);
File file = new File(NEW_FILE_NAME);
final int expectedRowResult = 5;
Assertions.assertEquals(expectedRowResult, workbook.getSheetAt(0).getLastRowNum());
outputStream.close();
file.delete();
workbook.close();
}
}

@ -5,9 +5,10 @@ This module contains articles about Java 10 core features
### Relevant Articles: ### Relevant Articles:
- [Java 10 LocalVariable Type-Inference](http://www.baeldung.com/java-10-local-variable-type-inference) - [Java 10 LocalVariable Type-Inference](http://www.baeldung.com/java-10-local-variable-type-inference)
- [Guide to Java 10](http://www.baeldung.com/java-10-overview) - [New Features in Java 10](https://www.baeldung.com/java-10-overview)
- [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another) - [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another)
- [Deep Dive Into the New Java JIT Compiler Graal](https://www.baeldung.com/graal-java-jit-compiler) - [Deep Dive Into the New Java JIT Compiler Graal](https://www.baeldung.com/graal-java-jit-compiler)
- [Copying Sets in Java](https://www.baeldung.com/java-copy-sets) - [Copying Sets in Java](https://www.baeldung.com/java-copy-sets)
- [Converting between a List and a Set in Java](https://www.baeldung.com/convert-list-to-set-and-set-to-list) - [Converting between a List and a Set in Java](https://www.baeldung.com/convert-list-to-set-and-set-to-list)
- [Java IndexOutOfBoundsException “Source Does Not Fit in Dest”](https://www.baeldung.com/java-indexoutofboundsexception) - [Java IndexOutOfBoundsException “Source Does Not Fit in Dest”](https://www.baeldung.com/java-indexoutofboundsexception)
- [Collect a Java Stream to an Immutable Collection](https://www.baeldung.com/java-stream-immutable-collection)

@ -0,0 +1,20 @@
package com.baeldung.java10.streams;
import static java.util.stream.Collectors.toUnmodifiableList;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
public class StreamToImmutableJava10UnitTest {
@Test
public void whenUsingCollectorsToUnmodifiableList_thenSuccess() {
List<String> givenList = Arrays.asList("a", "b", "c");
List<String> result = givenList.stream()
.collect(toUnmodifiableList());
System.out.println(result.getClass());
}
}

@ -1,5 +1,4 @@
## Relevant Articles: ## Relevant Articles:
- [String API Updates in Java 12](https://www.baeldung.com/java12-string-api) - [String API Updates in Java 12](https://www.baeldung.com/java12-string-api)
- [Java 12 New Features](https://www.baeldung.com/java-12-new-features) - [New Features in Java 12](https://www.baeldung.com/java-12-new-features)

@ -1,4 +1,4 @@
### Relevant articles: ### Relevant articles:
- [Java Switch Statement](https://www.baeldung.com/java-switch) - [Java Switch Statement](https://www.baeldung.com/java-switch)
- [New Java 13 Features](https://www.baeldung.com/java-13-new-features) - [New Features in Java 13](https://www.baeldung.com/java-13-new-features)

@ -10,4 +10,4 @@ This module contains articles about Java 14.
- [Helpful NullPointerExceptions in Java 14](https://www.baeldung.com/java-14-nullpointerexception) - [Helpful NullPointerExceptions in Java 14](https://www.baeldung.com/java-14-nullpointerexception)
- [Foreign Memory Access API in Java 14](https://www.baeldung.com/java-foreign-memory-access) - [Foreign Memory Access API in Java 14](https://www.baeldung.com/java-foreign-memory-access)
- [Java 14 Record Keyword](https://www.baeldung.com/java-record-keyword) - [Java 14 Record Keyword](https://www.baeldung.com/java-record-keyword)
- [Java 14 New Features](https://www.baeldung.com/java-14-new-features) - [New Features in Java 14](https://www.baeldung.com/java-14-new-features)

@ -4,7 +4,7 @@ This module contains articles about core Java features that have been introduced
### Relevant Articles: ### Relevant Articles:
- [Java 9 New Features](https://www.baeldung.com/new-java-9) - [New Features in Java 9](https://www.baeldung.com/new-java-9)
- [Java 9 Variable Handles Demystified](http://www.baeldung.com/java-variable-handles) - [Java 9 Variable Handles Demystified](http://www.baeldung.com/java-variable-handles)
- [Exploring the New HTTP Client in Java 9 and 11](http://www.baeldung.com/java-9-http-client) - [Exploring the New HTTP Client in Java 9 and 11](http://www.baeldung.com/java-9-http-client)
- [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar) - [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar)

@ -0,0 +1,8 @@
package com.baeldung.annotations;
import javax.annotation.Generated;
@RetentionAnnotation
@Generated("Available only on source code")
public class AnnotatedClass {
}

@ -0,0 +1,12 @@
package com.baeldung.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
@Target(TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface RetentionAnnotation {
}

@ -0,0 +1,18 @@
package com.baeldung.annotations;
import org.junit.Test;
import java.lang.annotation.Annotation;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
public class AnnotatedClassUnitTest {
@Test
public void whenAnnotationRetentionPolicyRuntime_shouldAccess() {
AnnotatedClass anAnnotatedClass = new AnnotatedClass();
Annotation[] annotations = anAnnotatedClass.getClass().getAnnotations();
assertThat(annotations.length, is(1));
}
}

@ -3,4 +3,4 @@
This module contains articles about Java Character Class This module contains articles about Java Character Class
### Relevant Articles: ### Relevant Articles:
- [Character#isAlphabetic vs Character#isLetter](https://www.baeldung.com/java-character-isletter-isalphabetic) - [Character#isAlphabetic vs. Character#isLetter](https://www.baeldung.com/java-character-isletter-isalphabetic)

@ -5,3 +5,4 @@
### Relevant Articles: ### Relevant Articles:
- [ArrayList vs. LinkedList vs. HashMap in Java](https://www.baeldung.com/java-arraylist-vs-linkedlist-vs-hashmap) - [ArrayList vs. LinkedList vs. HashMap in Java](https://www.baeldung.com/java-arraylist-vs-linkedlist-vs-hashmap)
- [Java Deque vs. Stack](https://www.baeldung.com/java-deque-vs-stack)

@ -25,7 +25,7 @@
</dependencies> </dependencies>
<properties> <properties>
<assertj.version>3.18.0</assertj.version> <assertj.version>3.19.0</assertj.version>
</properties> </properties>
</project> </project>

@ -0,0 +1,91 @@
package com.baeldung.collections.dequestack;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.Iterator;
public class ArrayLifoStack<E> implements LifoStack<E> {
private final Deque<E> deque = new ArrayDeque<>();
@Override
public void push(E item) {
deque.addFirst(item);
}
@Override
public E pop() {
return deque.removeFirst();
}
@Override
public E peek() {
return deque.peekFirst();
}
// implementing methods from the Collection interface
@Override
public int size() {
return deque.size();
}
@Override
public boolean isEmpty() {
return deque.isEmpty();
}
@Override
public boolean contains(Object o) {
return deque.contains(o);
}
@Override
public Iterator<E> iterator() {
return deque.iterator();
}
@Override
public Object[] toArray() {
return deque.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return deque.toArray(a);
}
@Override
public boolean add(E e) {
return deque.add(e);
}
@Override
public boolean remove(Object o) {
return deque.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return deque.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends E> c) {
return deque.addAll(c);
}
@Override
public boolean removeAll(Collection<?> c) {
return deque.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return deque.retainAll(c);
}
@Override
public void clear() {
deque.clear();
}
}

@ -0,0 +1,12 @@
package com.baeldung.collections.dequestack;
import java.util.Collection;
public interface LifoStack<E> extends Collection<E> {
E peek();
E pop();
void push(E item);
}

@ -0,0 +1,90 @@
package com.baeldung.collections.dequestack;
import org.junit.jupiter.api.Test;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.Stack;
import static org.assertj.core.api.Assertions.assertThat;
class StackVsDequeUnitTest {
@Test
void givenAStack_whenAccessByIndex_thenElementCanBeRead() {
Stack<String> myStack = new Stack<>();
myStack.push("I am the 1st element."); //index 0
myStack.push("I am the 2nd element."); //index 1
myStack.push("I am the 3rd element."); //index 2
//access by index
assertThat(myStack.get(0)).isEqualTo("I am the 1st element.");
}
@Test
void givenAStack_whenIterate_thenFromBottomToTop() {
Stack<String> myStack = new Stack<>();
myStack.push("I am at the bottom.");
myStack.push("I am in the middle.");
myStack.push("I am at the top.");
Iterator<String> it = myStack.iterator();
assertThat(it).toIterable().containsExactly(
"I am at the bottom.",
"I am in the middle.",
"I am at the top.");
}
@Test
void givenAStack_whenAddOrRemoveByIndex_thenElementCanBeAddedOrRemoved() {
Stack<String> myStack = new Stack<>();
myStack.push("I am the 1st element.");
myStack.push("I am the 3rd element.");
assertThat(myStack.size()).isEqualTo(2);
//insert by index
myStack.add(1, "I am the 2nd element.");
assertThat(myStack.size()).isEqualTo(3);
assertThat(myStack.get(1)).isEqualTo("I am the 2nd element.");
//remove by index
myStack.remove(1);
assertThat(myStack.size()).isEqualTo(2);
}
@Test
void givenADeque_whenAddOrRemoveLastElement_thenTheLastElementCanBeAddedOrRemoved() {
Deque<String> myStack = new ArrayDeque<>();
myStack.push("I am the 1st element.");
myStack.push("I am the 2nd element.");
myStack.push("I am the 3rd element.");
assertThat(myStack.size()).isEqualTo(3);
//insert element to the bottom of the stack
myStack.addLast("I am the NEW element.");
assertThat(myStack.size()).isEqualTo(4);
assertThat(myStack.peek()).isEqualTo("I am the 3rd element.");
//remove element from the bottom of the stack
String removedStr = myStack.removeLast();
assertThat(myStack.size()).isEqualTo(3);
assertThat(removedStr).isEqualTo("I am the NEW element.");
}
@Test
void givenADeque_whenIterate_thenFromTopToBottom() {
Deque<String> myStack = new ArrayDeque<>();
myStack.push("I am at the bottom.");
myStack.push("I am in the middle.");
myStack.push("I am at the top.");
Iterator<String> it = myStack.iterator();
assertThat(it).toIterable().containsExactly(
"I am at the top.",
"I am in the middle.",
"I am at the bottom.");
}
}

@ -8,6 +8,7 @@ import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder; import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -18,12 +19,12 @@ import java.util.concurrent.TimeUnit;
@State(Scope.Thread) @State(Scope.Thread)
public class PrimitivesListPerformance { public class PrimitivesListPerformance {
private List<Integer> arrayList = new ArrayList<>(); private List<Integer> arrayList = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
private TIntArrayList tList = new TIntArrayList(); private TIntArrayList tList = new TIntArrayList(new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
private cern.colt.list.IntArrayList coltList = new cern.colt.list.IntArrayList(); private cern.colt.list.IntArrayList coltList = new cern.colt.list.IntArrayList(new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
private IntArrayList fastUtilList = new IntArrayList(); private IntArrayList fastUtilList = new IntArrayList(new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
private int getValue = 10; private int getValue = 4;
@Benchmark @Benchmark
public boolean addArrayList() { public boolean addArrayList() {

@ -7,4 +7,6 @@ This module contains articles about Map data structures in Java.
- [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps) - [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps)
- [The Map.computeIfAbsent() Method](https://www.baeldung.com/java-map-computeifabsent) - [The Map.computeIfAbsent() Method](https://www.baeldung.com/java-map-computeifabsent)
- [Collections.synchronizedMap vs. ConcurrentHashMap](https://www.baeldung.com/java-synchronizedmap-vs-concurrenthashmap) - [Collections.synchronizedMap vs. ConcurrentHashMap](https://www.baeldung.com/java-synchronizedmap-vs-concurrenthashmap)
- [Java HashMap Load Factor](https://www.baeldung.com/java-hashmap-load-factor)
- [Converting java.util.Properties to HashMap](https://www.baeldung.com/java-convert-properties-to-hashmap)
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-2) - More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-2)

@ -20,6 +20,11 @@
<artifactId>jmh-core</artifactId> <artifactId>jmh-core</artifactId>
<version>${jmh-core.version}</version> <version>${jmh-core.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies> </dependencies>
<properties> <properties>

@ -0,0 +1,39 @@
package com.baeldung.map.propertieshashmap;
import com.google.common.collect.Maps;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
public class PropertiesToHashMapConverter {
@SuppressWarnings({"rawtypes", "unchecked"})
public static HashMap<String, String> typeCastConvert(Properties prop) {
Map step1 = prop;
Map<String, String> step2 = (Map<String, String>) step1;
return new HashMap<>(step2);
}
public static HashMap<String, String> loopConvert(Properties prop) {
HashMap<String, String> retMap = new HashMap<>();
for (Map.Entry<Object, Object> entry : prop.entrySet()) {
retMap.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
}
return retMap;
}
public static HashMap<String, String> streamConvert(Properties prop) {
return prop.entrySet().stream().collect(
Collectors.toMap(
e -> String.valueOf(e.getKey()),
e -> String.valueOf(e.getValue()),
(prev, next) -> next, HashMap::new
));
}
public static HashMap<String, String> guavaConvert(Properties prop) {
return Maps.newHashMap(Maps.fromProperties(prop));
}
}

@ -0,0 +1,49 @@
package com.baeldung.map.hashmap.loadfactor;
import java.util.HashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
public class HashMapLoadFactorUnitTest {
@Test
public void whenCreateMapWithDefaultParam_thenSucces() {
Map<String, String> mapWithDefaultParams = new HashMap<>();
mapWithDefaultParams.put("1", "one");
mapWithDefaultParams.put("2", "two");
mapWithDefaultParams.put("3", "three");
mapWithDefaultParams.put("4", "four");
mapWithDefaultParams.put("5", "five");
Assert.assertEquals(5, mapWithDefaultParams.size());
}
@Test
public void whenCreateMapWithInitialCapacity_thenSucces() {
Map<String, String> mapWithInitialCapacity = new HashMap<>(5);
mapWithInitialCapacity.put("1", "one");
mapWithInitialCapacity.put("2", "two");
mapWithInitialCapacity.put("3", "three");
Assert.assertEquals(3, mapWithInitialCapacity.size());
}
@Test
public void whenCreateMapWithInitialCapacityAndLF_thenSucces() {
Map<String, String> mapWithInitialCapacityAndLF = new HashMap<>(5, 0.5f);
mapWithInitialCapacityAndLF.put("1", "one");
mapWithInitialCapacityAndLF.put("2", "two");
mapWithInitialCapacityAndLF.put("3", "three");
mapWithInitialCapacityAndLF.put("4", "four");
mapWithInitialCapacityAndLF.put("5", "five");
mapWithInitialCapacityAndLF.put("6", "six");
mapWithInitialCapacityAndLF.put("7", "seven");
mapWithInitialCapacityAndLF.put("8", "eight");
mapWithInitialCapacityAndLF.put("9", "nine");
mapWithInitialCapacityAndLF.put("10", "ten");
Assert.assertEquals(10, mapWithInitialCapacityAndLF.size());
}
}

@ -0,0 +1,192 @@
package com.baeldung.map.propertieshashmap;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.*;
class PropertiesToHashMapConverterUnitTest {
private Properties properties;
private final static String propertyFileName = "toHashMap.properties";
@BeforeEach
public void setup() throws IOException {
properties = new Properties();
try (InputStream is = getClass().getClassLoader().getResourceAsStream(propertyFileName)) {
if (is != null) {
properties.load(is);
}
}
}
@Test
public void havingPropertiesLoaded_whenCheck_thenEquals() {
assertEquals(3, properties.size());
assertEquals("str_value", properties.get("property1"));
assertEquals("123", properties.get("property2"));
assertEquals("", properties.get("property3"));
}
@Test
public void whenPropertiesModified_thenTypeSafeIssues() {
compromiseProperties(properties);
assertEquals(5, properties.size());
assertNull(properties.getProperty("property4"));
assertNotEquals(String.class, properties.get("property4").getClass());
assertEquals(456, properties.get("property4"));
assertNull(properties.getProperty("5"));
assertNotEquals(String.class, properties.get(5).getClass());
assertEquals(10.11, properties.get(5));
}
@Test
public void havingNonModifiedProperties_whenTypeCastConvert_thenNoTypeSafeIssues() {
HashMap<String, String> hMap = PropertiesToHashMapConverter.typeCastConvert(properties);
assertEquals(3, hMap.size());
assertEquals(String.class, hMap.get("property1").getClass());
assertEquals(properties.get("property1"), hMap.get("property1"));
assertEquals(String.class, hMap.get("property2").getClass());
assertEquals(properties.get("property2"), hMap.get("property2"));
assertEquals(String.class, hMap.get("property3").getClass());
assertEquals(properties.get("property3"), hMap.get("property3"));
}
@Test
public void havingModifiedProperties_whenTypeCastConvert_thenClassCastException() {
compromiseProperties(properties);
HashMap<String, String> hMap = PropertiesToHashMapConverter.typeCastConvert(properties);
assertEquals(5, hMap.size());
assertThrows(ClassCastException.class, () -> {
String s = hMap.get("property4");
});
assertEquals(Integer.class, ((Object) hMap.get("property4")).getClass());
assertNull(hMap.get("5"));
assertNotNull(hMap.get(5));
assertThrows(ClassCastException.class, () -> {
String s = hMap.get(5);
});
assertEquals(Double.class, ((Object) hMap.get(5)).getClass());
}
@Test
public void havingNonModifiedProperties_whenLoopConvert_thenNoTypeSafeIssues() {
HashMap<String, String> hMap = PropertiesToHashMapConverter.loopConvert(properties);
assertEquals(3, hMap.size());
assertEquals(String.class, hMap.get("property1").getClass());
assertEquals(properties.get("property1"), hMap.get("property1"));
assertEquals(String.class, hMap.get("property2").getClass());
assertEquals(properties.get("property2"), hMap.get("property2"));
assertEquals(String.class, hMap.get("property3").getClass());
assertEquals(properties.get("property3"), hMap.get("property3"));
}
@Test
public void havingModifiedProperties_whenLoopConvert_thenNoClassCastException() {
compromiseProperties(properties);
HashMap<String, String> hMap = PropertiesToHashMapConverter.loopConvert(properties);
assertEquals(5, hMap.size());
assertDoesNotThrow(() -> {
String s = hMap.get("property4");
});
assertEquals(String.class, hMap.get("property4").getClass());
assertEquals("456", hMap.get("property4"));
assertDoesNotThrow(() -> {
String s = hMap.get("5");
});
assertEquals("10.11", hMap.get("5"));
}
@Test
public void havingNonModifiedProperties_whenStreamConvert_thenNoTypeSafeIssues() {
HashMap<String, String> hMap = PropertiesToHashMapConverter.streamConvert(properties);
assertEquals(3, hMap.size());
assertEquals(String.class, hMap.get("property1").getClass());
assertEquals(properties.get("property1"), hMap.get("property1"));
assertEquals(String.class, hMap.get("property2").getClass());
assertEquals(properties.get("property2"), hMap.get("property2"));
assertEquals(String.class, hMap.get("property3").getClass());
assertEquals(properties.get("property3"), hMap.get("property3"));
}
@Test
public void havingModifiedProperties_whenStreamConvert_thenNoClassCastException() {
compromiseProperties(properties);
HashMap<String, String> hMap = PropertiesToHashMapConverter.streamConvert(properties);
assertEquals(5, hMap.size());
assertDoesNotThrow(() -> {
String s = hMap.get("property4");
});
assertEquals(String.class, hMap.get("property4").getClass());
assertEquals("456", hMap.get("property4"));
assertDoesNotThrow(() -> {
String s = hMap.get("5");
});
assertEquals("10.11", hMap.get("5"));
}
@Test
public void havingModifiedProperties_whenLoopConvertAndStreamConvert_thenHashMapsSame() {
compromiseProperties(properties);
HashMap<String, String> hMap1 = PropertiesToHashMapConverter.loopConvert(properties);
HashMap<String, String> hMap2 = PropertiesToHashMapConverter.streamConvert(properties);
assertEquals(hMap2, hMap1);
}
@Test
public void havingNonModifiedProperties_whenGuavaConvert_thenNoTypeSafeIssues() {
HashMap<String, String> hMap = PropertiesToHashMapConverter.guavaConvert(properties);
assertEquals(3, hMap.size());
assertEquals(String.class, hMap.get("property1").getClass());
assertEquals(properties.get("property1"), hMap.get("property1"));
assertEquals(String.class, hMap.get("property2").getClass());
assertEquals(properties.get("property2"), hMap.get("property2"));
assertEquals(String.class, hMap.get("property3").getClass());
assertEquals(properties.get("property3"), hMap.get("property3"));
}
@Test
public void havingModifiedProperties_whenGuavaConvert_thenUnableToConvertAndThrowException() {
compromiseProperties(properties);
assertThrows(Exception.class, () -> PropertiesToHashMapConverter.guavaConvert(properties));
}
@Test
public void havingModifiedPropertiesWithNoIntegerValue_whenGuavaConvert_thenNullPointerException() {
properties.put("property4", 456);
assertThrows(NullPointerException.class, () -> PropertiesToHashMapConverter.guavaConvert(properties));
}
@Test
public void havingModifiedPropertiesWithNoIntegerKey_whenGuavaConvert_thenClassCastException() {
properties.put(5, 10.11);
assertThrows(ClassCastException.class, () -> PropertiesToHashMapConverter.guavaConvert(properties));
}
private void compromiseProperties(Properties prop) {
prop.put("property4", 456);
prop.put(5, 10.11);
}
}

@ -0,0 +1,3 @@
property1=str_value
property2=123
property3=

@ -21,14 +21,16 @@ public class ThreadPoolInParallelStreamIntegrationTest {
long lastNum = 1_000_000; long lastNum = 1_000_000;
List<Long> aList = LongStream.rangeClosed(firstNum, lastNum).boxed().collect(Collectors.toList()); List<Long> aList = LongStream.rangeClosed(firstNum, lastNum).boxed().collect(Collectors.toList());
ForkJoinPool customThreadPool = new ForkJoinPool(4); ForkJoinPool customThreadPool = new ForkJoinPool(4);
long actualTotal = customThreadPool
.submit(() -> aList.parallelStream()
.reduce(0L, Long::sum))
.get();
try {
long actualTotal = customThreadPool
.submit(() -> aList.parallelStream().reduce(0L, Long::sum))
.get();
assertEquals((lastNum + firstNum) * lastNum / 2, actualTotal); assertEquals((lastNum + firstNum) * lastNum / 2, actualTotal);
} finally {
customThreadPool.shutdown();
}
} }
@Test @Test

@ -5,12 +5,12 @@ import com.google.common.io.CharSource;
import com.google.common.io.Files; import com.google.common.io.Files;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ReaderInputStream;
import org.junit.Test; import org.junit.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets;
public class JavaXToInputStreamUnitTest { public class JavaXToInputStreamUnitTest {
protected final Logger logger = LoggerFactory.getLogger(getClass()); protected final Logger logger = LoggerFactory.getLogger(getClass());
@ -28,7 +28,7 @@ public class JavaXToInputStreamUnitTest {
@Test @Test
public final void givenUsingGuava_whenConvertingStringToInputStream_thenCorrect() throws IOException { public final void givenUsingGuava_whenConvertingStringToInputStream_thenCorrect() throws IOException {
final String initialString = "text"; final String initialString = "text";
final InputStream targetStream = new ReaderInputStream(CharSource.wrap(initialString).openStream()); final InputStream targetStream = CharSource.wrap(initialString).asByteSource(StandardCharsets.UTF_8).openStream();
IOUtils.closeQuietly(targetStream); IOUtils.closeQuietly(targetStream);
} }

@ -17,7 +17,7 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.baeldung.servicemodule</groupId> <groupId>com.baeldung.servicemodule</groupId>
<artifactId>servicemodule</artifactId> <artifactId>servicemodule2</artifactId>
<version>${servicemodule.version}</version> <version>${servicemodule.version}</version>
</dependency> </dependency>
<dependency> <dependency>

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

@ -11,4 +11,5 @@ This module contains articles about core features in the Java language
- [The transient Keyword in Java](https://www.baeldung.com/java-transient-keyword) - [The transient Keyword in Java](https://www.baeldung.com/java-transient-keyword)
- [How to Access an Iteration Counter in a For Each Loop](https://www.baeldung.com/java-foreach-counter) - [How to Access an Iteration Counter in a For Each Loop](https://www.baeldung.com/java-foreach-counter)
- [Comparing Doubles in Java](https://www.baeldung.com/java-comparing-doubles) - [Comparing Doubles in Java](https://www.baeldung.com/java-comparing-doubles)
- [Guide to Implementing the compareTo Method](https://www.baeldung.com/java-compareto)
- [[<-- Prev]](/core-java-modules/core-java-lang-2) - [[<-- Prev]](/core-java-modules/core-java-lang-2)

@ -0,0 +1,5 @@
## Core Java Lang (Part 4)
This module contains articles about core features in the Java language
- [The Java final Keyword Impact on Performance](https://www.baeldung.com/java-final-performance)

@ -0,0 +1,47 @@
<?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-lang-4</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-lang-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>../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${jmh.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>core-java-lang-4</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<properties>
<jmh.version>1.28</jmh.version>
</properties>
</project>

@ -0,0 +1,34 @@
package com.baeldung.finalkeyword;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import java.util.concurrent.TimeUnit;
public class BenchmarkRunner {
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}
@Benchmark
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
public static String concatNonFinalStrings() {
String x = "x";
String y = "y";
return x + y;
}
@Benchmark
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
public static String concatFinalStrings() {
final String x = "x";
final String y = "y";
return x + y;
}
}

@ -0,0 +1,19 @@
package com.baeldung.finalkeyword;
import java.io.Console;
public class ClassVariableFinal {
static final boolean doX = false;
static final boolean doY = true;
public static void main(String[] args) {
Console console = System.console();
if (doX) {
console.writer().println("x");
} else if (doY) {
console.writer().println("y");
}
}
}

@ -0,0 +1,19 @@
package com.baeldung.finalkeyword;
import java.io.Console;
public class ClassVariableNonFinal {
static boolean doX = false;
static boolean doY = true;
public static void main(String[] args) {
Console console = System.console();
if (doX) {
console.writer().println("x");
} else if (doY) {
console.writer().println("y");
}
}
}

@ -4,6 +4,5 @@
### Relevant articles: ### Relevant articles:
- [Calculate Factorial in Java](https://www.baeldung.com/java-calculate-factorial)
- [Evaluating a Math Expression in Java](https://www.baeldung.com/java-evaluate-math-expression-string) - [Evaluating a Math Expression in Java](https://www.baeldung.com/java-evaluate-math-expression-string)
- More articles: [[<-- Prev]](/core-java-modules/core-java-lang-math-2) - More articles: [[<-- Prev]](/core-java-modules/core-java-lang-math-2)

@ -8,3 +8,4 @@ This module contains articles about generics in Java
- [Raw Types in Java](https://www.baeldung.com/raw-types-java) - [Raw Types in Java](https://www.baeldung.com/raw-types-java)
- [Super Type Tokens in Java Generics](https://www.baeldung.com/java-super-type-tokens) - [Super Type Tokens in Java Generics](https://www.baeldung.com/java-super-type-tokens)
- [Java Warning “unchecked conversion”](https://www.baeldung.com/java-unchecked-conversion) - [Java Warning “unchecked conversion”](https://www.baeldung.com/java-unchecked-conversion)
- [Java Warning “Unchecked Cast”](https://www.baeldung.com/java-warning-unchecked-cast)

@ -0,0 +1,26 @@
package com.baeldung.uncheckedcast;
import java.time.LocalDate;
import java.time.Month;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class UncheckedCast {
public static Map getRawMap() {
Map rawMap = new HashMap();
rawMap.put("date 1", LocalDate.of(2021, Month.FEBRUARY, 10));
rawMap.put("date 2", LocalDate.of(1992, Month.AUGUST, 8));
rawMap.put("date 3", LocalDate.of(1976, Month.NOVEMBER, 18));
return rawMap;
}
public static Map getRawMapWithMixedTypes() {
Map rawMap = new HashMap();
rawMap.put("date 1", LocalDate.of(2021, Month.FEBRUARY, 10));
rawMap.put("date 2", LocalDate.of(1992, Month.AUGUST, 8));
rawMap.put("date 3", LocalDate.of(1976, Month.NOVEMBER, 18));
rawMap.put("date 4", new Date());
return rawMap;
}
}

@ -0,0 +1,25 @@
package com.baeldung.uncheckedcast;
import org.junit.Assert;
import org.junit.Test;
import java.time.LocalDate;
import java.time.Month;
import java.util.Map;
public class UncheckedCastUnitTest {
@Test
public void givenRawMap_whenCastToTypedMap_shouldHaveCompilerWarning() {
Map<String, LocalDate> castFromRawMap = (Map<String, LocalDate>) UncheckedCast.getRawMap();
Assert.assertEquals(3, castFromRawMap.size());
Assert.assertEquals(castFromRawMap.get("date 2"), LocalDate.of(1992, Month.AUGUST, 8));
}
@Test(expected = ClassCastException.class)
public void givenMixTypedRawMap_whenCastToTypedMap_shouldThrowClassCastException() {
Map<String, LocalDate> castFromRawMap = (Map<String, LocalDate>) UncheckedCast.getRawMapWithMixedTypes();
Assert.assertEquals(4, castFromRawMap.size());
Assert.assertTrue(castFromRawMap.get("date 4").isAfter(castFromRawMap.get("date 3")));
}
}

@ -0,0 +1,131 @@
package com.baeldung.classfile;
import org.apache.commons.lang3.StringUtils;
import com.baeldung.classfile.HelloWorld.HelloSomeone;
public class Outer {
// Static Nested class
static class StaticNested {
public String message() {
return "This is a static Nested Class";
}
}
// Non-static Nested class
class Nested {
public String message() {
return "This is a non-static Nested Class";
}
}
// Local class
public String message() {
class Local {
private String message() {
return "This is a Local Class within a method";
}
}
Local local = new Local();
return local.message();
}
// Local class within if clause
public String message(String name) {
if (StringUtils.isEmpty(name)) {
class Local {
private String message() {
return "This is a Local Class within if clause";
}
}
Local local = new Local();
return local.message();
} else
return "Welcome to " + name;
}
// Anonymous Inner class extending a class
public String greet() {
Outer anonymous = new Outer() {
public String greet() {
return "Running Anonymous Class...";
}
};
return anonymous.greet();
}
// Anonymous inner class implementing an interface
public String greet(String name) {
HelloWorld helloWorld = new HelloWorld() {
public String greet(String name) {
return "Welcome to " + name;
}
};
return helloWorld.greet(name);
}
// Anonymous inner class implementing nested interface
public String greetSomeone(String name) {
HelloSomeone helloSomeOne = new HelloSomeone() {
public String greet(String name) {
return "Hello " + name;
}
};
return helloSomeOne.greet(name);
}
// Nested interface within a class
interface HelloOuter {
public String hello(String name);
}
// Enum within a class
enum Color {
RED, GREEN, BLUE;
}
}
interface HelloWorld {
public String greet(String name);
// Nested class within an interface
class InnerClass {
public String greet(String name) {
return "Inner class within an interface";
}
}
// Nested interface within an interfaces
interface HelloSomeone {
public String greet(String name);
}
// Enum within an interface
enum Directon {
NORTH, SOUTH, EAST, WEST;
}
}
enum Level {
LOW, MEDIUM, HIGH;
}
enum Foods {
DRINKS, EATS;
// Enum within Enum
enum DRINKS {
APPLE_JUICE, COLA;
}
enum EATS {
POTATO, RICE;
}
}

@ -0,0 +1,46 @@
package com.baeldung.classfile;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import com.baeldung.classfile.Outer.Nested;
public class OuterUnitTest {
@Test
public void when_static_nestedClass_then_verifyOutput() {
Outer.StaticNested nestedClass = new Outer.StaticNested();
assertEquals("This is a static Nested Class", nestedClass.message());
}
@Test
public void when_nestedClass_then_verifyOutput() {
Outer outer = new Outer();
Nested nestedClass = outer.new Nested();
assertEquals("This is a non-static Nested Class", nestedClass.message());
}
@Test
public void when_localClass_then_verifyOutput() {
Outer outer = new Outer();
assertEquals("This is a Local Class within a method", outer.message());
}
@Test
public void when_localClassInIfClause_then_verifyOutput() {
Outer outer = new Outer();
assertEquals("Welcome to Baeldung", outer.message("Baeldung"));
assertEquals("This is a Local Class within if clause", outer.message(""));
}
@Test
public void when_anonymousClass_then_verifyOutput() {
Outer outer = new Outer();
assertEquals("Running Anonymous Class...", outer.greet());
}
@Test
public void when_anonymousClassHelloWorld_then_verifyOutput() {
Outer outer = new Outer();
assertEquals("Welcome to Baeldung", outer.greet("Baeldung"));
}
}

@ -14,5 +14,12 @@
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<relativePath>../</relativePath> <relativePath>../</relativePath>
</parent> </parent>
<dependencies>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.6.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project> </project>

@ -0,0 +1,64 @@
package com.baeldung.selector;
import org.junit.Test;
import java.io.IOException;
import java.nio.channels.Pipe;
import java.nio.channels.SelectableChannel;
import java.nio.channels.Selector;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import static org.assertj.core.api.Assertions.assertThat;
import static java.nio.channels.SelectionKey.OP_READ;
public class SelectorManualTest {
@Test
public void whenWakeUpCalledOnSelector_thenBlockedThreadReturns() throws IOException, InterruptedException {
Pipe pipe = Pipe.open();
Selector selector = Selector.open();
SelectableChannel channel = pipe.source();
channel.configureBlocking(false);
channel.register(selector, OP_READ);
List<String> invocationStepsTracker = Collections.synchronizedList(new ArrayList<>());
CountDownLatch latch = new CountDownLatch(1);
Thread thread = new Thread(() -> {
invocationStepsTracker.add(">> Count down");
latch.countDown();
try {
invocationStepsTracker.add(">> Start select");
selector.select();
invocationStepsTracker.add(">> End select");
} catch (IOException e) {
e.printStackTrace();
}
});
invocationStepsTracker.add(">> Start await");
thread.start();
latch.await();
invocationStepsTracker.add(">> End await");
invocationStepsTracker.add(">> Wakeup thread");
selector.wakeup();
channel.close();
assertThat(invocationStepsTracker)
.containsExactly(
">> Start await",
">> Count down",
">> Start select",
">> End await",
">> Wakeup thread",
">> End select"
);
}
}

@ -4,3 +4,4 @@
- [Set Field Value With Reflection](https://www.baeldung.com/java-set-private-field-value) - [Set Field Value With Reflection](https://www.baeldung.com/java-set-private-field-value)
- [Checking If a Method is Static Using Reflection in Java](https://www.baeldung.com/java-check-method-is-static) - [Checking If a Method is Static Using Reflection in Java](https://www.baeldung.com/java-check-method-is-static)
- [Checking if a Java Class is abstract Using Reflection](https://www.baeldung.com/java-reflection-is-class-abstract) - [Checking if a Java Class is abstract Using Reflection](https://www.baeldung.com/java-reflection-is-class-abstract)
- [Invoking a Private Method in Java](https://www.baeldung.com/java-call-private-method)

@ -14,6 +14,15 @@
<relativePath>../</relativePath> <relativePath>../</relativePath>
</parent> </parent>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build> <build>
<finalName>core-java-reflection-2</finalName> <finalName>core-java-reflection-2</finalName>
<resources> <resources>
@ -40,5 +49,6 @@
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
<source.version>1.8</source.version> <source.version>1.8</source.version>
<target.version>1.8</target.version> <target.version>1.8</target.version>
<spring.version>5.3.4</spring.version>
</properties> </properties>
</project> </project>

@ -0,0 +1,18 @@
package com.baeldung.reflection.access.privatemethods;
public class LongArrayUtil {
public static int indexOf(long[] array, long target) {
return indexOf(array, target, 0, array.length);
}
private static int indexOf(long[] array, long target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
}

@ -0,0 +1,28 @@
package com.baeldung.reflection.access.privatemethods;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.lang.reflect.Method;
import static org.junit.jupiter.api.Assertions.assertEquals;
class InvokePrivateMethodsUnitTest {
private final long[] someLongArray = new long[] { 1L, 2L, 1L, 4L, 2L };
@Test
void whenSearchingForLongValueInSubsequenceUsingReflection_thenTheCorrectIndexOfTheValueIsReturned() throws Exception {
Method indexOfMethod = LongArrayUtil.class.getDeclaredMethod("indexOf", long[].class, long.class, int.class, int.class);
indexOfMethod.setAccessible(true);
assertEquals(2, indexOfMethod.invoke(LongArrayUtil.class, someLongArray, 1L, 1, someLongArray.length), "The index should be 2.");
}
@Test
void whenSearchingForLongValueInSubsequenceUsingSpring_thenTheCorrectIndexOfTheValueIsReturned() throws Exception {
int indexOfSearchTarget = ReflectionTestUtils.invokeMethod(LongArrayUtil.class, "indexOf", someLongArray, 1L, 1, someLongArray.length);
assertEquals(2, indexOfSearchTarget, "The index should be 2.");
}
}

@ -15,4 +15,5 @@ This module contains articles about core Java Security
- [Security Context Basics: User, Subject and Principal](https://www.baeldung.com/security-context-basics) - [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) - [Java AES Encryption and Decryption](https://www.baeldung.com/java-aes-encryption-decryption)
- [InvalidAlgorithmParameterException: Wrong IV Length](https://www.baeldung.com/java-invalidalgorithmparameter-exception) - [InvalidAlgorithmParameterException: Wrong IV Length](https://www.baeldung.com/java-invalidalgorithmparameter-exception)
- [The java.security.egd JVM Option](https://www.baeldung.com/java-security-egd)
- More articles: [[<-- prev]](/core-java-modules/core-java-security) - More articles: [[<-- prev]](/core-java-modules/core-java-security)

@ -82,6 +82,7 @@
<module>core-java-lang</module> <module>core-java-lang</module>
<module>core-java-lang-2</module> <module>core-java-lang-2</module>
<module>core-java-lang-3</module> <module>core-java-lang-3</module>
<module>core-java-lang-4</module>
<module>core-java-lang-math</module> <module>core-java-lang-math</module>
<module>core-java-lang-math-2</module> <module>core-java-lang-math-2</module>
<module>core-java-lang-math-3</module> <module>core-java-lang-math-3</module>

@ -10,10 +10,8 @@ public class CircularBuffer<E> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public CircularBuffer(int capacity) { public CircularBuffer(int capacity) {
this.capacity = (capacity < 1) ? DEFAULT_CAPACITY : capacity; this.capacity = (capacity < 1) ? DEFAULT_CAPACITY : capacity;
this.data = (E[]) new Object[capacity]; this.data = (E[]) new Object[this.capacity];
this.readSequence = 0; this.readSequence = 0;
this.writeSequence = -1; this.writeSequence = -1;
} }

@ -5,7 +5,7 @@ import org.slf4j.LoggerFactory;
public class CircularLinkedList { public class CircularLinkedList {
final Logger LOGGER = LoggerFactory.getLogger(CircularLinkedList.class); final Logger logger = LoggerFactory.getLogger(CircularLinkedList.class);
private Node head = null; private Node head = null;
private Node tail = null; private Node tail = null;
@ -42,25 +42,30 @@ public class CircularLinkedList {
} }
public void deleteNode(int valueToDelete) { public void deleteNode(int valueToDelete) {
Node currentNode = head; Node currentNode = head;
if (head == null) {
if (head != null) { return;
if (currentNode.value == valueToDelete) { }
head = head.nextNode;
tail.nextNode = head;
} else {
do { do {
Node nextNode = currentNode.nextNode; Node nextNode = currentNode.nextNode;
if (nextNode.value == valueToDelete) { if (nextNode.value == valueToDelete) {
if (tail == head) {
head = null;
tail = null;
} else {
currentNode.nextNode = nextNode.nextNode; currentNode.nextNode = nextNode.nextNode;
if (head == nextNode) {
head = head.nextNode;
}
if (tail == nextNode) {
tail = currentNode;
}
}
break; break;
} }
currentNode = currentNode.nextNode; currentNode = nextNode;
} while (currentNode != head); } while (currentNode != head);
} }
}
}
public void traverseList() { public void traverseList() {
@ -68,7 +73,7 @@ public class CircularLinkedList {
if (head != null) { if (head != null) {
do { do {
LOGGER.info(currentNode.value + " "); logger.info(currentNode.value + " ");
currentNode = currentNode.nextNode; currentNode = currentNode.nextNode;
} while (currentNode != head); } while (currentNode != head);
} }

@ -1,10 +1,10 @@
package com.baeldung.circularlinkedlist; package com.baeldung.circularlinkedlist;
import org.junit.Test;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class CircularLinkedListUnitTest { public class CircularLinkedListUnitTest {
@Test @Test
@ -23,7 +23,7 @@ public class CircularLinkedListUnitTest {
} }
@Test @Test
public void givenACircularLinkedList_WhenDeletingElements_ThenListDoesNotContainThoseElements() { public void givenACircularLinkedList_WhenDeletingInOrderHeadMiddleTail_ThenListDoesNotContainThoseElements() {
CircularLinkedList cll = createCircularLinkedList(); CircularLinkedList cll = createCircularLinkedList();
assertTrue(cll.containsNode(13)); assertTrue(cll.containsNode(13));
@ -39,6 +39,32 @@ public class CircularLinkedListUnitTest {
assertFalse(cll.containsNode(46)); assertFalse(cll.containsNode(46));
} }
@Test
public void givenACircularLinkedList_WhenDeletingInOrderTailMiddleHead_ThenListDoesNotContainThoseElements() {
CircularLinkedList cll = createCircularLinkedList();
assertTrue(cll.containsNode(46));
cll.deleteNode(46);
assertFalse(cll.containsNode(46));
assertTrue(cll.containsNode(1));
cll.deleteNode(1);
assertFalse(cll.containsNode(1));
assertTrue(cll.containsNode(13));
cll.deleteNode(13);
assertFalse(cll.containsNode(13));
}
@Test
public void givenACircularLinkedListWithOneNode_WhenDeletingElement_ThenListDoesNotContainTheElement() {
CircularLinkedList cll = new CircularLinkedList();
cll.addNode(1);
cll.deleteNode(1);
assertFalse(cll.containsNode(1));
}
private CircularLinkedList createCircularLinkedList() { private CircularLinkedList createCircularLinkedList() {
CircularLinkedList cll = new CircularLinkedList(); CircularLinkedList cll = new CircularLinkedList();

@ -3,3 +3,4 @@
- [Introduction to Docker Compose](https://www.baeldung.com/docker-compose) - [Introduction to Docker Compose](https://www.baeldung.com/docker-compose)
- [Reusing Docker Layers with Spring Boot](https://www.baeldung.com/docker-layers-spring-boot) - [Reusing Docker Layers with Spring Boot](https://www.baeldung.com/docker-layers-spring-boot)
- [Running Spring Boot with PostgreSQL in Docker Compose](https://www.baeldung.com/spring-boot-postgresql-docker) - [Running Spring Boot with PostgreSQL in Docker Compose](https://www.baeldung.com/spring-boot-postgresql-docker)
- [How To Configure Java Heap Size Inside a Docker Container](https://www.baeldung.com/ops/docker-jvm-heap-size)

@ -0,0 +1,4 @@
FROM openjdk:8u92-jdk-alpine
COPY /src /src/
RUN mkdir /app && ls /src && javac /src/main/java/com/baeldung/docker/heapsizing/PrintXmxXms.java -d /app
CMD java -version && java $JAVA_OPTS -cp /app com.baeldung.docker.heapsizing.PrintXmxXms

@ -0,0 +1,61 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.baeldung.docker</groupId>
<artifactId>heap-sizing</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>heap-sizing</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<name>heapsizing-demo</name>
</image>
</configuration>
</plugin>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>2.7.1</version>
<configuration>
<to>
<image>heapsizing-demo-jib</image>
</to>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,19 @@
package com.baeldung.docker.heapsizing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.logging.Logger;
import static com.baeldung.docker.heapsizing.PrintXmxXms.logMemory;
@SpringBootApplication
public class HeapSizingApplication {
private static final Logger logger = Logger.getLogger(HeapSizingApplication.class.getName());
public static void main(String[] args) {
SpringApplication.run(HeapSizingApplication.class, args);
logMemory(logger);
}
}

@ -0,0 +1,36 @@
package com.baeldung.docker.heapsizing;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.util.logging.Level;
import java.util.logging.Logger;
public class PrintXmxXms {
private static final Logger logger = Logger.getLogger(PrintXmxXms.class.getName());
public static void main(String[] args) {
logMemory(logger);
}
/**
* We're reusing this method in HeapSizingApplication, therefore this method was extracted
* to avoid repetition.
*/
static void logMemory(Logger logger) {
float mb = 1024f * 1024f;
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
// xmx controls the maximum size of the memory allocation pool,
// which includes the heap, the garbage collector's survivor space, and other pools.
float xmx = memoryBean.getHeapMemoryUsage().getMax() / mb;
float xms = memoryBean.getHeapMemoryUsage().getInit() / mb;
logger.log(Level.INFO, "Initial Memory (xms) : {0}mb", xms);
logger.log(Level.INFO, "Max Memory (xmx) : {0}mb", xmx);
for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans()) {
logger.log(Level.INFO, "Pool: {0} (type {1}) = {2}", new Object[]{ mp.getName(), mp.getType(), mp.getUsage().getMax() / mb });
}
}
}

@ -1,3 +1,3 @@
### Relevant Articles: ### Relevant Articles:
- [Kotlin vs Java](https://www.baeldung.com/kotlin/kotlin-vs-java) - [Kotlin vs Java](https://www.baeldung.com/kotlin/vs-java)

@ -1,12 +1,12 @@
package com.baeldung.jackson.bidirection; package com.baeldung.jackson.bidirection;
import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonBackReference;
public class ItemWithRef { public class ItemWithRef {
public int id; public int id;
public String itemName; public String itemName;
@JsonManagedReference @JsonBackReference
public UserWithRef owner; public UserWithRef owner;
public ItemWithRef() { public ItemWithRef() {

@ -3,13 +3,13 @@ package com.baeldung.jackson.bidirection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference;
public class UserWithRef { public class UserWithRef {
public int id; public int id;
public String name; public String name;
@JsonBackReference @JsonManagedReference
public List<ItemWithRef> userItems; public List<ItemWithRef> userItems;
public UserWithRef() { public UserWithRef() {
@ -19,7 +19,7 @@ public class UserWithRef {
public UserWithRef(final int id, final String name) { public UserWithRef(final int id, final String name) {
this.id = id; this.id = id;
this.name = name; this.name = name;
userItems = new ArrayList<ItemWithRef>(); userItems = new ArrayList<>();
} }
public void addItem(final ItemWithRef item) { public void addItem(final ItemWithRef item) {

@ -1,7 +1,9 @@
package com.baeldung.jackson.bidirection; package com.baeldung.jackson.bidirection;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
@ -16,7 +18,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonBidirectionRelationUnitTest { public class JacksonBidirectionRelationUnitTest {
@Test(expected = JsonMappingException.class) @Test (expected = JsonMappingException.class)
public void givenBidirectionRelation_whenSerializing_thenException() throws JsonProcessingException { public void givenBidirectionRelation_whenSerializing_thenException() throws JsonProcessingException {
final User user = new User(1, "John"); final User user = new User(1, "John");
final Item item = new Item(2, "book", user); final Item item = new Item(2, "book", user);
@ -26,16 +28,39 @@ public class JacksonBidirectionRelationUnitTest {
} }
@Test @Test
public void givenBidirectionRelation_whenUsingJacksonReferenceAnnotation_thenCorrect() throws JsonProcessingException { public void givenBidirectionRelation_whenUsingJacksonReferenceAnnotationWithSerialization_thenCorrect() throws JsonProcessingException {
final UserWithRef user = new UserWithRef(1, "John"); final UserWithRef user = new UserWithRef(1, "John");
final ItemWithRef item = new ItemWithRef(2, "book", user); final ItemWithRef item = new ItemWithRef(2, "book", user);
user.addItem(item); user.addItem(item);
final String result = new ObjectMapper().writeValueAsString(item); final String itemJson = new ObjectMapper().writeValueAsString(item);
final String userJson = new ObjectMapper().writeValueAsString(user);
assertThat(result, containsString("book")); assertThat(itemJson, containsString("book"));
assertThat(result, containsString("John")); assertThat(itemJson, not(containsString("John")));
assertThat(result, not(containsString("userItems")));
assertThat(userJson, containsString("John"));
assertThat(userJson, containsString("userItems"));
assertThat(userJson, containsString("book"));
}
@Test
public void givenBidirectionRelation_whenUsingJacksonReferenceAnnotationWithDeserialization_thenCorrect() throws JsonProcessingException {
final UserWithRef user = new UserWithRef(1, "John");
final ItemWithRef item = new ItemWithRef(2, "book", user);
user.addItem(item);
final String itemJson = new ObjectMapper().writeValueAsString(item);
final String userJson = new ObjectMapper().writeValueAsString(user);
final ItemWithRef itemRead = new ObjectMapper().readValue(itemJson, ItemWithRef.class);
final UserWithRef userRead = new ObjectMapper().readValue(userJson, UserWithRef.class);
assertThat(itemRead.itemName, is("book"));
assertThat(itemRead.owner, nullValue());
assertThat(userRead.name, is("John"));
assertThat(userRead.userItems.get(0).itemName, is("book"));
} }
@Test @Test

@ -3,3 +3,4 @@
- [Java Map With Case-Insensitive Keys](https://www.baeldung.com/java-map-with-case-insensitive-keys) - [Java Map With Case-Insensitive Keys](https://www.baeldung.com/java-map-with-case-insensitive-keys)
- [Using a Byte Array as Map Key in Java](https://www.baeldung.com/java-map-key-byte-array) - [Using a Byte Array as Map Key in Java](https://www.baeldung.com/java-map-key-byte-array)
- [Using the Map.Entry Java Class](https://www.baeldung.com/java-map-entry) - [Using the Map.Entry Java Class](https://www.baeldung.com/java-map-entry)
- [Optimizing HashMaps Performance](https://www.baeldung.com/java-hashmap-optimize-performance)

@ -0,0 +1,6 @@
package com.baeldung.map.hashing;
class Member {
Integer id;
String name;
}

@ -0,0 +1,8 @@
package com.baeldung.map.hashing;
public class MemberWithBadHashing extends Member {
@Override
public int hashCode() {
return name.hashCode();
}
}

@ -0,0 +1,18 @@
package com.baeldung.map.hashing;
import com.google.common.base.Charsets;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
public class MemberWithGuavaHashing extends Member {
@Override
public int hashCode() {
HashFunction hashFunction = Hashing.murmur3_32();
return hashFunction.newHasher()
.putInt(id)
.putString(name, Charsets.UTF_8)
.hash().hashCode();
}
}

@ -0,0 +1,18 @@
package com.baeldung.map.hashing;
public class MemberWithId extends Member {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MemberWithId that = (MemberWithId) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return id;
}
}

@ -0,0 +1,23 @@
package com.baeldung.map.hashing;
import java.util.Objects;
public class MemberWithIdAndName extends Member {
public static final int PRIME = 31;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MemberWithObjects that = (MemberWithObjects) o;
return Objects.equals(id, that.id) &&
Objects.equals(name, that.name);
}
@Override
public int hashCode() {
int result = id.hashCode();
result = PRIME * result + (name == null ? 0 : name.hashCode());
return result;
}
}

@ -0,0 +1,19 @@
package com.baeldung.map.hashing;
import java.util.Objects;
public class MemberWithObjects extends Member {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MemberWithObjects that = (MemberWithObjects) o;
return Objects.equals(id, that.id) &&
Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}

@ -0,0 +1,76 @@
package com.baeldung.map.hashing;
import com.google.common.base.Stopwatch;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import java.util.HashMap;
import java.util.SplittableRandom;
import java.util.function.Supplier;
public class HashingUnitTest {
public static final int SAMPLES = 1000000;
private SplittableRandom random = new SplittableRandom();
private String[] names = {"John", "Adam", "Suzie"};
@Test
void givenPrimitiveByteArrayKey_whenRetrievingFromMap_shouldRetrieveDifferentObjects() {
// bad hashing example is prohibitively slow for bigger samples
// Duration[] badHashing = testDuration(MemberWithBadHashing::new);
Duration[] withId = testDuration(MemberWithId::new);
Duration[] withObjects = testDuration(MemberWithObjects::new);
Duration[] withIdAndName = testDuration(MemberWithIdAndName::new);
// System.out.println("Inserting with bad hashing:");
// System.out.println(badHashing[0]);
// System.out.println("Getting with bad hashing:");
// System.out.println(badHashing[1]);
System.out.println("Inserting with id hashing:");
System.out.println(withId[0]);
System.out.println("Getting with id hashing:");
System.out.println(withId[1]);
System.out.println("Inserting with id and name hashing:");
System.out.println(withIdAndName[0]);
System.out.println("Getting with id and name hashing:");
System.out.println(withIdAndName[1]);
System.out.println("Inserting with Objects hashing:");
System.out.println(withObjects[0]);
System.out.println("Getting with Objects hashing:");
System.out.println(withObjects[1]);
}
private String randomName() {
return names[random.nextInt(2)];
}
private <T extends Member> Duration[] testDuration(Supplier<T> factory) {
HashMap<T, String> map = new HashMap<>();
Stopwatch stopwatch = Stopwatch.createUnstarted();
stopwatch.start();
for(int i = 0; i < SAMPLES; i++) {
T member = factory.get();
member.id = i;
member.name = randomName();
map.put(member, member.name);
}
stopwatch.stop();
Duration elapsedInserting = stopwatch.elapsed();
stopwatch.reset();
stopwatch.start();
for (T key : map.keySet()) {
map.get(key);
}
stopwatch.stop();
Duration elapsedGetting = stopwatch.elapsed();
stopwatch.reset();
return new Duration[]{elapsedInserting, elapsedGetting};
}
}

@ -20,7 +20,7 @@ public class JavaRMIIntegrationTest {
MessengerServiceImpl server = new MessengerServiceImpl(); MessengerServiceImpl server = new MessengerServiceImpl();
server.createStubAndBind(); server.createStubAndBind();
} catch (RemoteException e) { } catch (RemoteException e) {
fail("Exception Occurred"); fail("Exception Occurred: " + e);
} }
} }
@ -34,11 +34,9 @@ public class JavaRMIIntegrationTest {
String expectedMessage = "Server Message"; String expectedMessage = "Server Message";
assertEquals(responseMessage, expectedMessage); assertEquals(responseMessage, expectedMessage);
} catch (RemoteException e) { } catch (RemoteException | NotBoundException e) {
fail("Exception Occurred"); fail("Exception Occurred: " + e);
} catch (NotBoundException nb) { };
fail("Exception Occurred");
}
} }
} }

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

@ -7,7 +7,7 @@ It contains the code of a simple API for some CRUD operations built using Spring
- Maven - Maven
- JDK 8 - JDK 8
- MongoDB - MongoDB (Note: for the Write Extracted Data to a File Using JMeter example MongoDB is not required)
### Running ### Running
@ -36,6 +36,14 @@ Or create a new one via a POST:
$ curl -X POST -H "Content-Type:application/json" -d '{ "firstName" : "Dassi", "lastName" : "Orleando", "phoneNumber": "+237 545454545", "email": "mymail@yahoo.fr" }' localhost:8080/students $ curl -X POST -H "Content-Type:application/json" -d '{ "firstName" : "Dassi", "lastName" : "Orleando", "phoneNumber": "+237 545454545", "email": "mymail@yahoo.fr" }' localhost:8080/students
``` ```
### Available UUID API
You can view the test response using curl:
```bash
$ curl localhost:8080/api/uuid
```
Now with default configurations it will be available at: [http://localhost:8080](http://localhost:8080) Now with default configurations it will be available at: [http://localhost:8080](http://localhost:8080)
Enjoy it :) Enjoy it :)
@ -44,3 +52,4 @@ Enjoy it :)
- [Intro to Performance Testing using JMeter](https://www.baeldung.com/jmeter) - [Intro to Performance Testing using JMeter](https://www.baeldung.com/jmeter)
- [Configure Jenkins to Run and Show JMeter Tests](https://www.baeldung.com/jenkins-and-jmeter) - [Configure Jenkins to Run and Show JMeter Tests](https://www.baeldung.com/jenkins-and-jmeter)
- [Write Extracted Data to a File Using JMeter](https://www.baeldung.com/jmeter-write-to-file)

@ -0,0 +1,18 @@
package com.baeldung.controller;
import com.baeldung.model.Response;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
import static java.lang.String.format;
@RestController
public class RetrieveUuidController {
@GetMapping("/api/uuid")
public Response uuid() {
return new Response(format("Test message... %s.", UUID.randomUUID()));
}
}

@ -0,0 +1,40 @@
package com.baeldung.model;
import java.time.Instant;
import java.util.UUID;
public class Response {
private Instant timestamp;
private UUID uuid;
private String message;
public Response(String message) {
this.timestamp = Instant.now();
this.uuid = UUID.randomUUID();
this.message = message;
}
public Instant getTimestamp() {
return timestamp;
}
public void setTimestamp(Instant timestamp) {
this.timestamp = timestamp;
}
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.4.1">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
<stringProp name="TestPlan.comments">To run this test plan you must also be running the Spring application &quot;JmeterApplication&quot; That can be found in this directory</stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">1</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">1</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
</ThreadGroup>
<hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Call GET Test endpoint " enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/api/test</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree>
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="JSON Extractor" enabled="true">
<stringProp name="JSONPostProcessor.referenceNames">message</stringProp>
<stringProp name="JSONPostProcessor.jsonPathExprs">$.message</stringProp>
<stringProp name="JSONPostProcessor.match_numbers">1</stringProp>
<boolProp name="JSONPostProcessor.compute_concat">true</boolProp>
<stringProp name="JSONPostProcessor.defaultValues">NOT_FOUND</stringProp>
</JSONPostProcessor>
<hashTree/>
<BeanShellPostProcessor guiclass="TestBeanGUI" testclass="BeanShellPostProcessor" testname="Response to file using BeanShell PostProcessor" enabled="true">
<stringProp name="filename"></stringProp>
<stringProp name="parameters"></stringProp>
<boolProp name="resetInterpreter">false</boolProp>
<stringProp name="script">FileWriter fWriter = new FileWriter(&quot;<path>/result.txt&quot;, true);
BufferedWriter buff = new BufferedWriter(fWriter);
buff.write(&quot;Response Code : &quot; + ctx.getPreviousResult().getResponseCode());
buff.write(System.getProperty(&quot;line.separator&quot;));
buff.write(&quot;Response Headers : &quot; + ctx.getPreviousResult().getResponseHeaders());
buff.write(System.getProperty(&quot;line.separator&quot;));
buff.write(&quot;Response Body : &quot; + new String(ctx.getPreviousResult().getResponseData()));
buff.write(&quot;More complex extraction : &quot; + vars.get(&quot;message&quot;));
buff.close();
fWriter.close();</stringProp>
</BeanShellPostProcessor>
<hashTree/>
<ResultSaver guiclass="ResultSaverGui" testclass="ResultSaver" testname="Response to file using file write Listener" enabled="true">
<stringProp name="FileSaver.filename">response</stringProp>
<boolProp name="FileSaver.errorsonly">false</boolProp>
<boolProp name="FileSaver.successonly">false</boolProp>
<boolProp name="FileSaver.skipsuffix">false</boolProp>
<boolProp name="FileSaver.skipautonumber">false</boolProp>
</ResultSaver>
<hashTree/>
</hashTree>
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<url>true</url>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>

@ -0,0 +1,35 @@
package com.baeldung;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
class JmeterIntegrationTest {
MockMvc mvc;
public JmeterIntegrationTest(WebApplicationContext wac) {
this.mvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
@Test
void whenCallingUUIDController_thenWeShouldRecieveRandomizedResponse() throws Exception {
MockHttpServletResponse response = mvc.perform(get("/api/uuid"))
.andDo(print())
.andExpect(status().isOk())
.andReturn()
.getResponse();
assertThat(response.getContentAsString())
.contains("Test message...");
}
}

@ -0,0 +1,13 @@
# Kubernetes Java API Sample Code
This module contains sample code used to show how to use the Kubernetes client Java API.
Before running those samples, make sure that your environment is correctly configured to access
a working Kubernetes cluster.
An easy way to check that everything is working as expected is issuing any *kubectl get* command:
```shell
$ kubectl get nodes
```
If you get a valid response, then you're good to go.

@ -0,0 +1,41 @@
<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>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>kubernetes-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>k8s-intro</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java</artifactId>
<version>11.0.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<!-- http://maven.apache.org/plugins/maven-compiler-plugin/ -->
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -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,31 @@
/**
*
*/
package com.baeldung.kubernetes.intro;
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 ListNodes {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
ApiClient client = Config.defaultClient();
CoreV1Api api = new CoreV1Api(client);
V1NodeList nodeList = api.listNode(null, null, null, null, null, null, null, null, 10, false);
nodeList.getItems()
.stream()
.forEach((node) -> System.out.println(node.getMetadata()));
}
}

@ -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 ListNodesLiveTest {
@Test
void whenListNodes_thenSuccess() throws Exception {
ListNodes.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[] {});
}
}

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

13
kubernetes/pom.xml Normal file

@ -0,0 +1,13 @@
<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>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>kubernetes-parent</artifactId>
<packaging>pom</packaging>
<modules>
<module>k8s-intro</module>
</modules>
</project>

@ -7,5 +7,6 @@ This module contains articles about HTTP libraries.
- [Jetty ReactiveStreams HTTP Client](https://www.baeldung.com/jetty-reactivestreams-http-client) - [Jetty ReactiveStreams HTTP Client](https://www.baeldung.com/jetty-reactivestreams-http-client)
- [Decode an OkHttp JSON Response](https://www.baeldung.com/okhttp-json-response) - [Decode an OkHttp JSON Response](https://www.baeldung.com/okhttp-json-response)
- [Retrofit 2 Dynamic URL](https://www.baeldung.com/retrofit-dynamic-url) - [Retrofit 2 Dynamic URL](https://www.baeldung.com/retrofit-dynamic-url)
- [Adding Interceptors in OkHTTP](https://www.baeldung.com/java-okhttp-interceptors)
- More articles [[<-- prev]](/libraries-http) - More articles [[<-- prev]](/libraries-http)

@ -19,6 +19,11 @@
<artifactId>okhttp</artifactId> <artifactId>okhttp</artifactId>
<version>${okhttp.version}</version> <version>${okhttp.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
<version>${okhttp.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
@ -81,9 +86,9 @@
</dependencies> </dependencies>
<properties> <properties>
<okhttp.version>3.14.2</okhttp.version> <okhttp.version>4.9.1</okhttp.version>
<gson.version>2.8.5</gson.version> <gson.version>2.8.5</gson.version>
<mockwebserver.version>3.14.2</mockwebserver.version> <mockwebserver.version>4.9.1</mockwebserver.version>
<jetty.httpclient.version>1.0.3</jetty.httpclient.version> <jetty.httpclient.version>1.0.3</jetty.httpclient.version>
<jetty.server.version>9.4.19.v20190610</jetty.server.version> <jetty.server.version>9.4.19.v20190610</jetty.server.version>
<rxjava2.version>2.2.11</rxjava2.version> <rxjava2.version>2.2.11</rxjava2.version>

@ -0,0 +1,18 @@
package com.baeldung.okhttp.interceptors;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Response;
public class CacheControlResponeInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response.newBuilder()
.header("Cache-Control", "no-store")
.build();
}
}

@ -0,0 +1,21 @@
package com.baeldung.okhttp.interceptors;
public class ErrorMessage {
private final int status;
private final String detail;
public ErrorMessage(int status, String detail) {
this.status = status;
this.detail = detail;
}
public int getStatus() {
return status;
}
public String getDetail() {
return detail;
}
}

@ -0,0 +1,32 @@
package com.baeldung.okhttp.interceptors;
import java.io.IOException;
import com.google.gson.Gson;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class ErrorResponseInterceptor implements Interceptor {
public static final MediaType APPLICATION_JSON = MediaType.get("application/json; charset=utf-8");
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
if(!response.isSuccessful()) {
Gson gson = new Gson();
String body = gson.toJson(new ErrorMessage(response.code(), "The response from the server was not OK"));
ResponseBody responseBody = ResponseBody.create(body, APPLICATION_JSON);
return response.newBuilder()
.body(responseBody)
.build();
}
return response;
}
}

@ -0,0 +1,25 @@
package com.baeldung.okhttp.interceptors;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class SimpleLoggingInterceptor implements Interceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleLoggingInterceptor.class);
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
LOGGER.info("Intercepted headers: {} from URL: {}", request.headers(), request.url());
return chain.proceed(request);
}
}

@ -0,0 +1,90 @@
package com.baeldung.okhttp.interceptors;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import org.junit.Rule;
import org.junit.Test;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import okhttp3.logging.HttpLoggingInterceptor.Level;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
public class InterceptorIntegrationTest {
@Rule
public MockWebServer server = new MockWebServer();
@Test
public void givenSimpleLogginInterceptor_whenRequestSent_thenHeadersLogged() throws IOException {
server.enqueue(new MockResponse().setBody("Hello Baeldung Readers!"));
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new SimpleLoggingInterceptor())
.build();
Request request = new Request.Builder()
.url(server.url("/greeting"))
.header("User-Agent", "A Baeldung Reader")
.build();
try (Response response = client.newCall(request).execute()) {
assertEquals("Response code should be: ", 200, response.code());
assertEquals("Body should be: ", "Hello Baeldung Readers!", response.body().string());
}
}
@Test
public void givenResponseInterceptor_whenRequestSent_thenCacheControlSetToNoStore() throws IOException {
server.enqueue(new MockResponse().setBody("Hello Baeldung Readers!"));
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(getHttpLogger())
.addInterceptor(new CacheControlResponeInterceptor())
.build();
Request request = new Request.Builder()
.url(server.url("/greeting"))
.header("User-Agent", "A Baeldung Reader")
.build();
try (Response response = client.newCall(request).execute()) {
assertEquals("Response code should be: ", 200, response.code());
assertEquals("Body should be: ", "Hello Baeldung Readers!", response.body().string());
assertEquals("Response cache-control should be", "no-store", response.header("Cache-Control"));
}
}
@Test
public void givenErrorResponseInterceptor_whenResponseIs500_thenBodyIsJsonWithStatus() throws IOException {
server.enqueue(new MockResponse().setResponseCode(500).setBody("Hello Baeldung Readers!"));
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(getHttpLogger())
.addInterceptor(new ErrorResponseInterceptor())
.build();
Request request = new Request.Builder()
.url(server.url("/greeting"))
.header("User-Agent", "A Baeldung Reader")
.build();
try (Response response = client.newCall(request).execute()) {
assertEquals("Response code should be: ", 500, response.code());
assertEquals("Body should be: ", "{\"status\":500,\"detail\":\"The response from the server was not OK\"}",
response.body().string());
}
}
private HttpLoggingInterceptor getHttpLogger() {
HttpLoggingInterceptor logger = new HttpLoggingInterceptor();
logger.setLevel(Level.HEADERS);
return logger;
}
}

@ -0,0 +1,3 @@
### Relevant Articles:
- [Generate WSDL Stubs with Maven](https://www.baeldung.com/maven-wsdl-stubs)

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