commit
9f508c34a7
|
@ -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)
|
||||||
|
|
|
@ -11,3 +11,4 @@ This module contains articles about Java 10 core features
|
||||||
- [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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -8,4 +8,5 @@ This module contains articles about Map data structures in Java.
|
||||||
- [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)
|
- [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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 @@
|
||||||
- [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 HashMap’s Performance](https://www.baeldung.com/java-hashmap-optimize-performance)
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,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,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>
|
|
@ -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)
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>maven-plugins</artifactId>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>jaxws</artifactId>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>jaxws-maven-plugin</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>wsimport</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<wsdlDirectory>${project.basedir}/src/main/resources/</wsdlDirectory>
|
||||||
|
<packageName>com.baeldung.soap.ws.client</packageName>
|
||||||
|
<sourceDestDir>
|
||||||
|
${project.build.directory}/generated-sources/
|
||||||
|
</sourceDestDir>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-verifier-plugin</artifactId>
|
||||||
|
<version>${maven.verifier.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<verificationFile>../input-resources/verifications.xml</verificationFile>
|
||||||
|
<failOnError>false</failOnError>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.baeldung.soap.ws.client;
|
||||||
|
|
||||||
|
public class CountryNotFoundException extends RuntimeException {
|
||||||
|
|
||||||
|
public CountryNotFoundException() {
|
||||||
|
super("Country not found!");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.baeldung.soap.ws.client;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class CountryServiceClient {
|
||||||
|
|
||||||
|
private CountryService countryService;
|
||||||
|
|
||||||
|
public CountryServiceClient(CountryService countryService) {
|
||||||
|
this.countryService = countryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCapitalByCountryName(String countryName) {
|
||||||
|
return Optional.of(countryService.findByName(countryName))
|
||||||
|
.map(Country::getCapital).orElseThrow(CountryNotFoundException::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPopulationByCountryName(String countryName) {
|
||||||
|
return Optional.of(countryService.findByName(countryName))
|
||||||
|
.map(Country::getPopulation).orElseThrow(CountryNotFoundException::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Currency getCurrencyByCountryName(String countryName) {
|
||||||
|
return Optional.of(countryService.findByName(countryName))
|
||||||
|
.map(Country::getCurrency).orElseThrow(CountryNotFoundException::new);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
<!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. -->
|
||||||
|
<!-- Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. -->
|
||||||
|
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://server.ws.soap.baeldung.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://server.ws.soap.baeldung.com/" name="CountryServiceImplService">
|
||||||
|
<types>
|
||||||
|
<xsd:schema>
|
||||||
|
<xsd:import namespace="http://server.ws.soap.baeldung.com/" schemaLocation="country.xsd"/>
|
||||||
|
</xsd:schema>
|
||||||
|
</types>
|
||||||
|
<message name="findByName">
|
||||||
|
<part name="arg0" type="xsd:string"/>
|
||||||
|
</message>
|
||||||
|
<message name="findByNameResponse">
|
||||||
|
<part name="return" type="tns:country"/>
|
||||||
|
</message>
|
||||||
|
<portType name="CountryService">
|
||||||
|
<operation name="findByName">
|
||||||
|
<input wsam:Action="http://server.ws.soap.baeldung.com/CountryService/findByNameRequest" message="tns:findByName"/>
|
||||||
|
<output wsam:Action="http://server.ws.soap.baeldung.com/CountryService/findByNameResponse" message="tns:findByNameResponse"/>
|
||||||
|
</operation>
|
||||||
|
</portType>
|
||||||
|
<binding name="CountryServiceImplPortBinding" type="tns:CountryService">
|
||||||
|
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>
|
||||||
|
<operation name="findByName">
|
||||||
|
<soap:operation soapAction=""/>
|
||||||
|
<input>
|
||||||
|
<soap:body use="literal" namespace="http://server.ws.soap.baeldung.com/"/>
|
||||||
|
</input>
|
||||||
|
<output>
|
||||||
|
<soap:body use="literal" namespace="http://server.ws.soap.baeldung.com/"/>
|
||||||
|
</output>
|
||||||
|
</operation>
|
||||||
|
</binding>
|
||||||
|
<service name="CountryServiceImplService">
|
||||||
|
<port name="CountryServiceImplPort" binding="tns:CountryServiceImplPortBinding">
|
||||||
|
<soap:address location="http://localhost:8888/ws/country"/>
|
||||||
|
</port>
|
||||||
|
</service>
|
||||||
|
</definitions>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. -->
|
||||||
|
<xs:schema xmlns:tns="http://server.ws.soap.baeldung.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="1.0"
|
||||||
|
targetNamespace="http://server.ws.soap.baeldung.com/">
|
||||||
|
|
||||||
|
<xs:complexType name="country">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="capital" type="xs:string" minOccurs="0"></xs:element>
|
||||||
|
<xs:element name="currency" type="tns:currency" minOccurs="0"></xs:element>
|
||||||
|
<xs:element name="name" type="xs:string" minOccurs="0"></xs:element>
|
||||||
|
<xs:element name="population" type="xs:int"></xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:simpleType name="currency">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="EUR"></xs:enumeration>
|
||||||
|
<xs:enumeration value="INR"></xs:enumeration>
|
||||||
|
<xs:enumeration value="USD"></xs:enumeration>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
</xs:schema>
|
|
@ -0,0 +1,73 @@
|
||||||
|
package com.baeldung.soap.ws.client;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
class CountryServiceClientUnitTest {
|
||||||
|
|
||||||
|
CountryServiceClient countryServiceClient;
|
||||||
|
CountryService countryService;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
countryService = mock(CountryService.class);
|
||||||
|
countryServiceClient = new CountryServiceClient(countryService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Get capital by country name when country not found")
|
||||||
|
@Test
|
||||||
|
void givenCountryDoesNotExist_whenGetCapitalByCountryName_thenThrowsCountryNotFoundException() {
|
||||||
|
doThrow(CountryNotFoundException.class).when(countryService).findByName(any());
|
||||||
|
Assertions.assertThrows(CountryNotFoundException.class, () -> countryServiceClient.getCapitalByCountryName(any()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Get capital by country name when country is India then should return capital")
|
||||||
|
@Test
|
||||||
|
void givenCountryIndia_whenGetCapitalByCountryName_thenShouldReturnCapital() {
|
||||||
|
Country country = mock(Country.class);
|
||||||
|
|
||||||
|
doReturn("New Delhi").when(country).getCapital();
|
||||||
|
doReturn(country).when(countryService).findByName("India");
|
||||||
|
|
||||||
|
Assertions.assertEquals("New Delhi", countryServiceClient.getCapitalByCountryName("India"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Get population by country name when country not found")
|
||||||
|
@Test
|
||||||
|
void givenCountryDoesNotExist_getPopulationByCountryName_thenThrowsCountryNotFoundException() {
|
||||||
|
doThrow(CountryNotFoundException.class).when(countryService).findByName(any());
|
||||||
|
Assertions.assertThrows(CountryNotFoundException.class, () -> countryServiceClient.getPopulationByCountryName(any()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Get population by country name when country is India then should return population")
|
||||||
|
@Test
|
||||||
|
void givenCountryIndia_getPopulationByCountryName_thenShouldReturnPopulation() {
|
||||||
|
Country country = mock(Country.class);
|
||||||
|
|
||||||
|
doReturn(1000000).when(country).getPopulation();
|
||||||
|
doReturn(country).when(countryService).findByName("India");
|
||||||
|
|
||||||
|
Assertions.assertEquals(1000000, countryServiceClient.getPopulationByCountryName("India"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Get currency by country name when country not found")
|
||||||
|
@Test
|
||||||
|
void givenCountryDoesNotExist_getCurrencyByCountryName_thenThrowsCountryNotFoundException() {
|
||||||
|
doThrow(CountryNotFoundException.class).when(countryService).findByName(any());
|
||||||
|
Assertions.assertThrows(CountryNotFoundException.class, () -> countryServiceClient.getCurrencyByCountryName(any()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Get currency by country name when country is India then should return currency")
|
||||||
|
@Test
|
||||||
|
void givenCountryIndia_getCurrencyByCountryName_thenShouldReturnCurrency() {
|
||||||
|
Country country = mock(Country.class);
|
||||||
|
|
||||||
|
doReturn(Currency.INR).when(country).getCurrency();
|
||||||
|
doReturn(country).when(countryService).findByName("India");
|
||||||
|
|
||||||
|
Assertions.assertEquals(Currency.INR, countryServiceClient.getCurrencyByCountryName("India"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>custom-rule</module>
|
<module>custom-rule</module>
|
||||||
<module>maven-enforcer</module>
|
<module>maven-enforcer</module>
|
||||||
|
<module>jaxws</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
<rest-assured.version>3.3.0</rest-assured.version>
|
<rest-assured.version>3.3.0</rest-assured.version>
|
||||||
<!-- plugins -->
|
<!-- plugins -->
|
||||||
<thin.version>1.0.22.RELEASE</thin.version>
|
<thin.version>1.0.22.RELEASE</thin.version>
|
||||||
<spring-boot.version>2.4.0</spring-boot.version>
|
<spring-boot.version>2.4.3</spring-boot.version>
|
||||||
<aspectjweaver.version>1.9.1</aspectjweaver.version>
|
<aspectjweaver.version>1.9.1</aspectjweaver.version>
|
||||||
<!-- this property can be removed once we update Mockito version in the main pom.xml -->
|
<!-- this property can be removed once we update Mockito version in the main pom.xml -->
|
||||||
<mockito.version>3.4.0</mockito.version>
|
<mockito.version>3.4.0</mockito.version>
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<spring.version>5.2.8.RELEASE</spring.version>
|
<spring.version>5.3.3</spring.version>
|
||||||
<spring-security.version>5.2.3.RELEASE</spring-security.version>
|
<spring-security.version>5.2.3.RELEASE</spring-security.version>
|
||||||
<spring-boot-starter-test.version>1.5.10.RELEASE</spring-boot-starter-test.version>
|
<spring-boot-starter-test.version>1.5.10.RELEASE</spring-boot-starter-test.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class Application implements CommandLineRunner {
|
||||||
LOGGER.info("@@ findByFirstName() call...");
|
LOGGER.info("@@ findByFirstName() call...");
|
||||||
repository.findByFirstName("Franz")
|
repository.findByFirstName("Franz")
|
||||||
.forEach(person -> LOGGER.info(person.toString()));
|
.forEach(person -> LOGGER.info(person.toString()));
|
||||||
LOGGER.info("@@ findByFirstName() call...");
|
LOGGER.info("@@ updateByFirstName() call...");
|
||||||
repository.updateByFirstName(2L, "Date Inferno");
|
repository.updateByFirstName(2L, "Date Inferno");
|
||||||
repository.findAll()
|
repository.findAll()
|
||||||
.forEach(person -> LOGGER.info(person.toString()));
|
.forEach(person -> LOGGER.info(person.toString()));
|
||||||
|
|
|
@ -1,23 +1,20 @@
|
||||||
package com.baeldung.springdatajdbcintro.repository;
|
package com.baeldung.springdatajdbcintro.repository;
|
||||||
|
|
||||||
import java.util.List;
|
import com.baeldung.springdatajdbcintro.entity.Person;
|
||||||
|
|
||||||
import org.springframework.data.jdbc.repository.query.Modifying;
|
import org.springframework.data.jdbc.repository.query.Modifying;
|
||||||
import org.springframework.data.jdbc.repository.query.Query;
|
import org.springframework.data.jdbc.repository.query.Query;
|
||||||
import org.springframework.data.repository.CrudRepository;
|
import org.springframework.data.repository.CrudRepository;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import com.baeldung.springdatajdbcintro.entity.Person;
|
import java.util.List;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface PersonRepository extends CrudRepository<Person,Long> {
|
public interface PersonRepository extends CrudRepository<Person, Long> {
|
||||||
|
|
||||||
@Query("select * from person where first_name=:firstName")
|
List<Person> findByFirstName(String firstName);
|
||||||
List<Person> findByFirstName(@Param("firstName") String firstName);
|
|
||||||
|
|
||||||
@Modifying
|
@Modifying
|
||||||
@Query("UPDATE person SET first_name = :name WHERE id = :id")
|
@Query("UPDATE person SET first_name = :name WHERE id = :id")
|
||||||
boolean updateByFirstName(@Param("id") Long id, @Param("name") String name);
|
boolean updateByFirstName(@Param("id") Long id, @Param("name") String name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ This module contains articles about annotations used in Spring Data JPA
|
||||||
|
|
||||||
- [DDD Aggregates and @DomainEvents](https://www.baeldung.com/spring-data-ddd)
|
- [DDD Aggregates and @DomainEvents](https://www.baeldung.com/spring-data-ddd)
|
||||||
- [JPA @Embedded And @Embeddable](https://www.baeldung.com/jpa-embedded-embeddable)
|
- [JPA @Embedded And @Embeddable](https://www.baeldung.com/jpa-embedded-embeddable)
|
||||||
- [Spring Data JPA @Modifying Annotation](https://www.baeldung.com/spring-data-jpa-modifying-annotation)
|
|
||||||
- [Spring JPA @Embedded and @EmbeddedId](https://www.baeldung.com/spring-jpa-embedded-method-parameters)
|
- [Spring JPA @Embedded and @EmbeddedId](https://www.baeldung.com/spring-jpa-embedded-method-parameters)
|
||||||
- [Programmatic Transaction Management in Spring](https://www.baeldung.com/spring-programmatic-transaction-management)
|
- [Programmatic Transaction Management in Spring](https://www.baeldung.com/spring-programmatic-transaction-management)
|
||||||
- [JPA Entity Lifecycle Events](https://www.baeldung.com/jpa-entity-lifecycle-events)
|
- [JPA Entity Lifecycle Events](https://www.baeldung.com/jpa-entity-lifecycle-events)
|
||||||
|
|
|
@ -12,6 +12,7 @@ This module contains articles about Spring Data JPA used in enterprise applicati
|
||||||
- [Working with Lazy Element Collections in JPA](https://www.baeldung.com/java-jpa-lazy-collections)
|
- [Working with Lazy Element Collections in JPA](https://www.baeldung.com/java-jpa-lazy-collections)
|
||||||
- [Custom Naming Convention with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-custom-naming)
|
- [Custom Naming Convention with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-custom-naming)
|
||||||
- [Partial Data Update with Spring Data](https://www.baeldung.com/spring-data-partial-update)
|
- [Partial Data Update with Spring Data](https://www.baeldung.com/spring-data-partial-update)
|
||||||
|
- [Spring Data JPA @Modifying Annotation](https://www.baeldung.com/spring-data-jpa-modifying-annotation)
|
||||||
|
|
||||||
### Eclipse Config
|
### Eclipse Config
|
||||||
After importing the project into Eclipse, you may see the following error:
|
After importing the project into Eclipse, you may see the following error:
|
||||||
|
|
|
@ -93,6 +93,9 @@ public interface UserRepository extends JpaRepository<User, Integer> , UserRepos
|
||||||
@Query("delete User u where u.active = false")
|
@Query("delete User u where u.active = false")
|
||||||
int deleteDeactivatedUsers();
|
int deleteDeactivatedUsers();
|
||||||
|
|
||||||
|
@Query("delete User u where u.active = false")
|
||||||
|
int deleteDeactivatedUsersWithNoModifyingAnnotation();
|
||||||
|
|
||||||
@Modifying(clearAutomatically = true, flushAutomatically = true)
|
@Modifying(clearAutomatically = true, flushAutomatically = true)
|
||||||
@Query(value = "alter table USERS add column deleted int(1) not null default 0", nativeQuery = true)
|
@Query(value = "alter table USERS add column deleted int(1) not null default 0", nativeQuery = true)
|
||||||
void addDeletedColumn();
|
void addDeletedColumn();
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.baeldung.boot.daos;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
|
@ -21,6 +22,7 @@ import java.util.function.Predicate;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class UserRepositoryCommon {
|
public class UserRepositoryCommon {
|
||||||
|
@ -520,6 +522,22 @@ public class UserRepositoryCommon {
|
||||||
assertEquals(1, deletedUsersCount);
|
assertEquals(1, deletedUsersCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Transactional
|
||||||
|
public void givenTwoUsers_whenDeleteDeactivatedUsersWithNoModifyingAnnotation_ThenException() {
|
||||||
|
User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1);
|
||||||
|
usr01.setLastLoginDate(LocalDate.now());
|
||||||
|
User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.com", 0);
|
||||||
|
usr02.setLastLoginDate(LocalDate.of(2018, 7, 20));
|
||||||
|
usr02.setActive(false);
|
||||||
|
|
||||||
|
userRepository.save(usr01);
|
||||||
|
userRepository.save(usr02);
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> userRepository.deleteDeactivatedUsersWithNoModifyingAnnotation())
|
||||||
|
.isInstanceOf(InvalidDataAccessApiUsageException.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
public void givenTwoUsers_whenAddDeletedColumn_ThenUsersHaveDeletedColumn() {
|
public void givenTwoUsers_whenAddDeletedColumn_ThenUsersHaveDeletedColumn() {
|
||||||
|
|
8
pom.xml
8
pom.xml
|
@ -471,7 +471,7 @@
|
||||||
<module>json-path</module>
|
<module>json-path</module>
|
||||||
<module>jsoup</module>
|
<module>jsoup</module>
|
||||||
<module>jta</module>
|
<module>jta</module>
|
||||||
|
<module>kubernetes</module>
|
||||||
<!-- <module>lagom</module> --> <!-- Not a maven project -->
|
<!-- <module>lagom</module> --> <!-- Not a maven project -->
|
||||||
<module>language-interop</module>
|
<module>language-interop</module>
|
||||||
<module>libraries-2</module>
|
<module>libraries-2</module>
|
||||||
|
@ -531,7 +531,7 @@
|
||||||
<module>protobuffer</module>
|
<module>protobuffer</module>
|
||||||
|
|
||||||
<module>quarkus</module>
|
<module>quarkus</module>
|
||||||
<module>quarkus-extension</module>
|
<!-- <module>quarkus-extension</module> --> <!-- Module broken, fixing in http://team.baeldung.com/browse/JAVA-4770 -->
|
||||||
|
|
||||||
<module>rabbitmq</module>
|
<module>rabbitmq</module>
|
||||||
<!-- <module>raml</module> --> <!-- Not a maven project -->
|
<!-- <module>raml</module> --> <!-- Not a maven project -->
|
||||||
|
@ -992,7 +992,7 @@
|
||||||
<module>protobuffer</module>
|
<module>protobuffer</module>
|
||||||
|
|
||||||
<module>quarkus</module>
|
<module>quarkus</module>
|
||||||
<module>quarkus-extension</module>
|
<!-- <module>quarkus-extension</module> --> <!-- Module broken, fixing in http://team.baeldung.com/browse/JAVA-4770 -->
|
||||||
|
|
||||||
<module>rabbitmq</module>
|
<module>rabbitmq</module>
|
||||||
<!-- <module>raml</module> --> <!-- Not a maven project -->
|
<!-- <module>raml</module> --> <!-- Not a maven project -->
|
||||||
|
@ -1370,7 +1370,7 @@
|
||||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<log4j.version>1.2.17</log4j.version>
|
<log4j.version>1.2.17</log4j.version>
|
||||||
<esapi.version>2.1.0.1</esapi.version>
|
<esapi.version>2.2.2.0</esapi.version>
|
||||||
<jmh-core.version>1.19</jmh-core.version>
|
<jmh-core.version>1.19</jmh-core.version>
|
||||||
<jmh-generator.version>1.19</jmh-generator.version>
|
<jmh-generator.version>1.19</jmh-generator.version>
|
||||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||||
|
|
|
@ -174,7 +174,7 @@
|
||||||
<jsonb-api.version>1.0</jsonb-api.version>
|
<jsonb-api.version>1.0</jsonb-api.version>
|
||||||
<geronimo-json_1.1_spec.version>1.0</geronimo-json_1.1_spec.version>
|
<geronimo-json_1.1_spec.version>1.0</geronimo-json_1.1_spec.version>
|
||||||
<commons-collections4.version>4.1</commons-collections4.version>
|
<commons-collections4.version>4.1</commons-collections4.version>
|
||||||
<jetty-reactive-httpclient.version>1.0.3</jetty-reactive-httpclient.version>
|
<jetty-reactive-httpclient.version>1.1.6</jetty-reactive-httpclient.version>
|
||||||
<okhttp.version>4.0.1</okhttp.version>
|
<okhttp.version>4.0.1</okhttp.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.baeldung.boot.readonlyrepository;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Book
|
||||||
|
{
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
private String author;
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(String author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.baeldung.boot.readonlyrepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface BookReadOnlyRepository extends ReadOnlyRepository<Book, Long> {
|
||||||
|
|
||||||
|
List<Book> findByAuthor(String author);
|
||||||
|
|
||||||
|
List<Book> findByTitle(String title);
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.boot.readonlyrepository;
|
||||||
|
|
||||||
|
import org.springframework.data.repository.NoRepositoryBean;
|
||||||
|
import org.springframework.data.repository.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@NoRepositoryBean
|
||||||
|
public interface ReadOnlyRepository<T, ID> extends Repository<T, ID> {
|
||||||
|
|
||||||
|
Optional<T> findById(ID id);
|
||||||
|
|
||||||
|
List<T> findAll();
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.baeldung.boot.readonlyrepository;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class ReadOnlyRepositoryApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(ReadOnlyRepositoryApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.baeldung.boot.readonlyrepository;
|
||||||
|
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
|
||||||
|
public interface BookRepository extends BookReadOnlyRepository, CrudRepository<Book, Long> {
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.baeldung.boot.readonlyrepository;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
@SpringBootTest( classes = ReadOnlyRepositoryApplication.class )
|
||||||
|
public class ReadOnlyRepositoryUnitTest
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private BookRepository bookRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BookReadOnlyRepository bookReadOnlyRepository;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenBooks_whenUsingReadOnlyRepository_thenGetThem() {
|
||||||
|
Book aChristmasCarolCharlesDickens = new Book();
|
||||||
|
aChristmasCarolCharlesDickens.setTitle("A Christmas Carol");
|
||||||
|
aChristmasCarolCharlesDickens.setAuthor("Charles Dickens");
|
||||||
|
bookRepository.save(aChristmasCarolCharlesDickens);
|
||||||
|
|
||||||
|
Book greatExpectationsCharlesDickens = new Book();
|
||||||
|
greatExpectationsCharlesDickens.setTitle("Great Expectations");
|
||||||
|
greatExpectationsCharlesDickens.setAuthor("Charles Dickens");
|
||||||
|
bookRepository.save(greatExpectationsCharlesDickens);
|
||||||
|
|
||||||
|
Book greatExpectationsKathyAcker = new Book();
|
||||||
|
greatExpectationsKathyAcker.setTitle("Great Expectations");
|
||||||
|
greatExpectationsKathyAcker.setAuthor("Kathy Acker");
|
||||||
|
bookRepository.save(greatExpectationsKathyAcker);
|
||||||
|
|
||||||
|
List<Book> charlesDickensBooks = bookReadOnlyRepository.findByAuthor("Charles Dickens");
|
||||||
|
Assertions.assertEquals(2, charlesDickensBooks.size());
|
||||||
|
|
||||||
|
List<Book> greatExpectationsBooks = bookReadOnlyRepository.findByTitle("Great Expectations");
|
||||||
|
Assertions.assertEquals(2, greatExpectationsBooks.size());
|
||||||
|
|
||||||
|
List<Book> allBooks = bookReadOnlyRepository.findAll();
|
||||||
|
Assertions.assertEquals(3, allBooks.size());
|
||||||
|
|
||||||
|
Long bookId = allBooks.get(0).getId();
|
||||||
|
Book book = bookReadOnlyRepository.findById(bookId).orElseThrow(NoSuchElementException::new);
|
||||||
|
Assertions.assertNotNull(book);
|
||||||
|
}
|
||||||
|
}
|
|
@ -84,12 +84,6 @@
|
||||||
<version>${jquery.version}</version>
|
<version>${jquery.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-context</artifactId>
|
|
||||||
<version>${springcloud.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
<artifactId>httpclient</artifactId>
|
<artifactId>httpclient</artifactId>
|
||||||
|
@ -195,9 +189,7 @@
|
||||||
<jpa.version>2.2</jpa.version>
|
<jpa.version>2.2</jpa.version>
|
||||||
<guava.version>18.0</guava.version>
|
<guava.version>18.0</guava.version>
|
||||||
<subethasmtp.version>3.1.7</subethasmtp.version>
|
<subethasmtp.version>3.1.7</subethasmtp.version>
|
||||||
<springcloud.version>2.0.2.RELEASE</springcloud.version>
|
|
||||||
<httpclient.version>4.5.8</httpclient.version>
|
<httpclient.version>4.5.8</httpclient.version>
|
||||||
<spring-boot.version>2.3.3.RELEASE</spring-boot.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
package com.baeldung.charencoding.controller;
|
package com.baeldung.charencoding.controller;
|
||||||
|
|
||||||
import static org.mockito.Mockito.mock;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.mockito.Mockito.verify;
|
import org.springframework.mock.web.MockFilterChain;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import java.io.IOException;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
import org.springframework.web.filter.CharacterEncodingFilter;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import org.springframework.web.filter.CharacterEncodingFilter;
|
|
||||||
|
|
||||||
class CharEncodingCheckControllerUnitTest {
|
class CharEncodingCheckControllerUnitTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void whenCharEncodingFilter_thenVerifyEncoding() throws ServletException, IOException {
|
void whenCharEncodingFilter_thenVerifyEncoding() throws ServletException, IOException {
|
||||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
HttpServletRequest request = new MockHttpServletRequest();
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = new MockHttpServletResponse();
|
||||||
FilterChain chain = mock(FilterChain.class);
|
FilterChain chain = new MockFilterChain();
|
||||||
|
|
||||||
CharacterEncodingFilter filter = new CharacterEncodingFilter();
|
CharacterEncodingFilter filter = new CharacterEncodingFilter();
|
||||||
filter.setEncoding("UTF-8");
|
filter.setEncoding("UTF-8");
|
||||||
|
@ -27,8 +28,8 @@ class CharEncodingCheckControllerUnitTest {
|
||||||
|
|
||||||
filter.doFilter(request, response, chain);
|
filter.doFilter(request, response, chain);
|
||||||
|
|
||||||
verify(request).setCharacterEncoding("UTF-8");
|
assertEquals("UTF-8", request.getCharacterEncoding());
|
||||||
verify(response).setCharacterEncoding("UTF-8");
|
assertEquals("UTF-8", response.getCharacterEncoding());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,4 +5,4 @@ This module contains articles about Spring Boot: JAX-RS vs Spring
|
||||||
|
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
|
|
||||||
- [REST API: JAX-RS vs Spring](https://www.baeldung.com/TBD)
|
- [REST API: JAX-RS vs Spring](https://www.baeldung.com/rest-api-jax-rs-vs-spring)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.baeldung.boot.properties.multidocument;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
@ -21,6 +22,7 @@ public class StagingMultidocumentFilesIntegrationTest {
|
||||||
private String baelRootProperty;
|
private String baelRootProperty;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("Fix and update https://www.baeldung.com/spring-boot-yaml-vs-properties article")
|
||||||
public void givenProductionProfileActive_whenApplicationStarts_thenDefaultPropertiesUser() {
|
public void givenProductionProfileActive_whenApplicationStarts_thenDefaultPropertiesUser() {
|
||||||
assertThat(baelCustomProperty).isEqualTo("stagingValue");
|
assertThat(baelCustomProperty).isEqualTo("stagingValue");
|
||||||
assertThat(baelRootProperty).isEqualTo("defaultRootLevelValue");
|
assertThat(baelRootProperty).isEqualTo("defaultRootLevelValue");
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
### Relevant Article:
|
||||||
|
|
||||||
|
- [Get All Endpoints in Spring Boot](https://www.baeldung.com/spring-boot-get-all-endpoints)
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.baeldung.web</groupId>
|
||||||
|
<artifactId>spring-boot-rest-2</artifactId>
|
||||||
|
<name>spring-boot-rest-2</name>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
<description>Spring Boot Rest Module</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-boot-2</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../parent-boot-2</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.springfox</groupId>
|
||||||
|
<artifactId>springfox-boot-starter</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.baeldung.endpoint;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class SpringBootRestApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SpringBootRestApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.endpoint.controller;
|
||||||
|
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class HelloController {
|
||||||
|
|
||||||
|
@GetMapping("/hello")
|
||||||
|
public ResponseEntity<String> hello() {
|
||||||
|
return ResponseEntity.ok("hello baeldung");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.baeldung.endpoint.listener;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class AnnotationDrivenEndpointsListener {
|
||||||
|
private final Logger LOGGER = LoggerFactory.getLogger("AnnotationDrivenEndpointsListener.class");
|
||||||
|
|
||||||
|
@EventListener
|
||||||
|
public void handleContextRefresh(ContextRefreshedEvent event) {
|
||||||
|
ApplicationContext applicationContext = event.getApplicationContext();
|
||||||
|
RequestMappingHandlerMapping requestMappingHandlerMapping = applicationContext
|
||||||
|
.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
|
||||||
|
Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping.getHandlerMethods();
|
||||||
|
map.forEach((key, value) -> LOGGER.info("{} {}", key, value));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.baeldung.endpoint.listener;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class EndpointsListener implements ApplicationListener<ContextRefreshedEvent> {
|
||||||
|
private final Logger LOGGER = LoggerFactory.getLogger("EndpointsListener.class");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||||
|
ApplicationContext applicationContext = event.getApplicationContext();
|
||||||
|
RequestMappingHandlerMapping requestMappingHandlerMapping = applicationContext
|
||||||
|
.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
|
||||||
|
Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping.getHandlerMethods();
|
||||||
|
map.forEach((key, value) -> LOGGER.info("{} {}", key, value));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.baeldung.endpoint.swagger;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import springfox.documentation.builders.PathSelectors;
|
||||||
|
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
|
import springfox.documentation.spi.DocumentationType;
|
||||||
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class SpringFoxConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Docket api() {
|
||||||
|
return new Docket(DocumentationType.SWAGGER_2)
|
||||||
|
.select()
|
||||||
|
.apis(RequestHandlerSelectors.any())
|
||||||
|
.paths(PathSelectors.any())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
management.endpoints.web.exposure.include=mappings
|
|
@ -79,7 +79,6 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-commons</artifactId>
|
<artifactId>spring-data-commons</artifactId>
|
||||||
<version>2.3.0.RELEASE</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -38,6 +38,11 @@
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
|
||||||
|
<version>${spring-cloud-netflix-zuul.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
@ -46,10 +51,6 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
|
@ -79,8 +80,8 @@
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<spring-cloud.version>Hoxton.SR4</spring-cloud.version>
|
<spring-cloud.version>2020.0.0</spring-cloud.version>
|
||||||
<spring-boot.version>2.3.3.RELEASE</spring-boot.version>
|
<spring-cloud-netflix-zuul.version>2.2.2.RELEASE</spring-cloud-netflix-zuul.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
<artifactId>spring-cloud-zuul-ratelimit</artifactId>
|
<artifactId>spring-cloud-zuul-ratelimit</artifactId>
|
||||||
<version>${rate.limit.version}</version>
|
<version>${rate.limit.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.baeldung.scheduling.dynamic;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
import org.springframework.scheduling.annotation.SchedulingConfigurer;
|
||||||
|
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ComponentScan("com.baeldung.scheduling.dynamic")
|
||||||
|
@EnableScheduling
|
||||||
|
public class DynamicSchedulingConfig implements SchedulingConfigurer {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TickService tickService;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Executor taskExecutor() {
|
||||||
|
return Executors.newSingleThreadScheduledExecutor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
|
||||||
|
taskRegistrar.setScheduler(taskExecutor());
|
||||||
|
taskRegistrar.addTriggerTask(
|
||||||
|
() -> tickService.tick(),
|
||||||
|
context -> {
|
||||||
|
Optional<Date> lastCompletionTime =
|
||||||
|
Optional.ofNullable(context.lastCompletionTime());
|
||||||
|
Instant nextExecutionTime =
|
||||||
|
lastCompletionTime.orElseGet(Date::new).toInstant()
|
||||||
|
.plusMillis(tickService.getDelay());
|
||||||
|
return Date.from(nextExecutionTime);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.baeldung.scheduling.dynamic;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TickService {
|
||||||
|
|
||||||
|
private long delay = 0;
|
||||||
|
|
||||||
|
public long getDelay() {
|
||||||
|
this.delay += 1000;
|
||||||
|
System.out.println("delaying " + this.delay + " milliseconds...");
|
||||||
|
return this.delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick() {
|
||||||
|
final long now = System.currentTimeMillis() / 1000;
|
||||||
|
System.out
|
||||||
|
.println("schedule tasks with dynamic delay - " + now);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.scheduling;
|
||||||
|
|
||||||
|
import com.baeldung.scheduling.dynamic.DynamicSchedulingConfig;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||||
|
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration(classes = {
|
||||||
|
DynamicSchedulingConfig.class}, loader = AnnotationConfigContextLoader.class)
|
||||||
|
public class DynamicSchedulingIntegrationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTickServiceTick() throws InterruptedException {
|
||||||
|
Thread.sleep(6000);
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,6 +35,7 @@
|
||||||
<module>spring-security-legacy-oidc</module>
|
<module>spring-security-legacy-oidc</module>
|
||||||
<module>spring-security-oidc</module>
|
<module>spring-security-oidc</module>
|
||||||
<module>spring-security-okta</module>
|
<module>spring-security-okta</module>
|
||||||
|
<module>spring-security-saml</module>
|
||||||
<module>spring-security-web-react</module>
|
<module>spring-security-web-react</module>
|
||||||
<module>spring-security-web-rest</module>
|
<module>spring-security-web-rest</module>
|
||||||
<module>spring-security-web-rest-basic-auth</module>
|
<module>spring-security-web-rest-basic-auth</module>
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.owasp.esapi</groupId>
|
<groupId>org.owasp.esapi</groupId>
|
||||||
<artifactId>esapi</artifactId>
|
<artifactId>esapi</artifactId>
|
||||||
<version>2.2.2.0</version>
|
<version>${esapi.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jsoup</groupId>
|
<groupId>org.jsoup</groupId>
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
### Relevant Articles:
|
||||||
|
|
||||||
|
- [A Guide to SAML with Spring Security](https://www.baeldung.com/spring-security-saml)
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?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/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>spring-security-saml</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<name>spring-security-saml</name>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-boot-2</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../parent-boot-2</relativePath>
|
||||||
|
</parent>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>Shibboleth</id>
|
||||||
|
<name>Shibboleth</name>
|
||||||
|
<url>https://build.shibboleth.net/nexus/content/repositories/releases/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security.extensions</groupId>
|
||||||
|
<artifactId>spring-security-saml2-core</artifactId>
|
||||||
|
<version>${saml2-core.spring.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>spring-security-saml</finalName>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<addResources>true</addResources>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>repackage</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<saml2-core.spring.version>1.0.10.RELEASE</saml2-core.spring.version>
|
||||||
|
</properties>
|
||||||
|
</project>
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.baeldung.saml;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Application {
|
||||||
|
public static void main(String... args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.saml.authentication;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.providers.ExpiringUsernameAuthenticationToken;
|
||||||
|
import org.springframework.security.saml.SAMLAuthenticationProvider;
|
||||||
|
import org.springframework.security.saml.SAMLCredential;
|
||||||
|
|
||||||
|
public class CustomSAMLAuthenticationProvider extends SAMLAuthenticationProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getEntitlements(SAMLCredential credential, Object userDetail) {
|
||||||
|
|
||||||
|
if(userDetail instanceof ExpiringUsernameAuthenticationToken) {
|
||||||
|
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
|
||||||
|
authorities.addAll(((ExpiringUsernameAuthenticationToken) userDetail).getAuthorities());
|
||||||
|
return authorities;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue