Merge branch 'master' into JAVA-2399-Update_spring-security-rest_module_to_use_Swagger_3.0.0

This commit is contained in:
kwoyke 2021-05-25 10:56:24 +02:00 committed by GitHub
commit 42a0c6d966
436 changed files with 3803 additions and 2068 deletions

View File

@ -7,3 +7,4 @@ This module contains articles about Java 11 core features
- [Guide to Java Reflection](http://www.baeldung.com/java-reflection)
- [Guide to Java 8s Collectors](https://www.baeldung.com/java-8-collectors)
- [New Features in Java 11](https://www.baeldung.com/java-11-new-features)
- [Getting the Java Version at Runtime](https://www.baeldung.com/get-java-version-runtime)

View File

@ -34,4 +34,4 @@
<maven.compiler.target>1.9</maven.compiler.target>
</properties>
</project>
</project>

View File

@ -7,7 +7,7 @@
<version>0.1.0-SNAPSHOT</version>
<name>core-java-9-streams</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
@ -25,4 +25,4 @@
</resources>
</build>
</project>
</project>

View File

@ -0,0 +1,8 @@
package com.baeldung.exceptions.illegalaccesserror;
public class Class1 {
public void bar() {
System.out.println("SUCCESS");
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.exceptions.illegalaccesserror;
public class Class2 {
public void foo() {
Class1 c1 = new Class1();
c1.bar();
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.exceptions.illegalaccesserror;
public class IllegalAccessErrorExample {
interface Baeldung {
public default void foobar() {
System.out.println("This is a default method.");
}
}
class Super {
private void foobar() {
System.out.println("SuperClass method foobar");
}
}
class MySubClass extends Super implements Baeldung {
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.exceptions.illegalaccesserror;
public class IllegalAccessErrorSolved {
interface BaeldungSolved {
public default void foobar() {
System.out.println("This is a default method.");
}
}
class SuperSolved {
public void foobar() {
System.out.println("SuperClass method foobar");
}
}
class MySubClassSolved extends SuperSolved implements BaeldungSolved {
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.exceptions.illegalaccesserror;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class IllegalAccessErrorExampleUnitTest {
@Test()
public void givenInterfaceDefaultMethOverriddenPrivateAccess_whenInvoked_thenIllegalAccessError() {
Assertions.assertThrows(IllegalAccessError.class, () -> {
new IllegalAccessErrorExample().new MySubClass().foobar();
});
}
@Test()
public void givenClass1Class2_whenSameClassDefintion_thenNoIllegalAccessError() {
Assertions.assertDoesNotThrow(() -> {
new Class2().foo();
});
}
}

View File

@ -0,0 +1,14 @@
package com.baeldung.exceptions.illegalaccesserror;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class IllegalAccessErrorSolvedUnitTest {
@Test()
public void givenInterfaceDefaultMethOverriddenNonPrivateAccess_whenInvoked_thenNoIllegalAccessError() {
Assertions.assertDoesNotThrow(() -> {
new IllegalAccessErrorSolved().new MySubClassSolved().foobar();
});
}
}

View File

@ -0,0 +1,28 @@
package com.baeldung.deserialization.vulnerabilities;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
public class BadThing implements Serializable {
private static final long serialVersionUID = 0L;
Object looselyDefinedThing;
String methodName;
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
try {
Method method = looselyDefinedThing.getClass().getMethod(methodName);
method.invoke(looselyDefinedThing);
} catch (Exception e) {
// handle error...
}
}
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
}
}

View File

@ -0,0 +1,14 @@
package com.baeldung.deserialization.vulnerabilities;
import java.io.IOException;
import java.io.Serializable;
public class MyCustomAttackObject implements Serializable {
public static void methodThatTriggersAttack() {
try {
Runtime.getRuntime().exec("echo \"Oh, no! I've been hacked\"");
} catch (IOException e) {
// handle error...
}
}
}

View File

@ -0,0 +1,40 @@
package com.baeldung.deserialization.vulnerabilities;
import org.junit.Test;
import org.junit.jupiter.api.DisplayName;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class BadThingUnitTest {
@Test
@DisplayName("When a BadThing object is deserialized, then code execution in MyCustomAttackObject is run.")
public void givenABadThingObject_whenItsDeserialized_thenExecutionIsRun() throws Exception {
BadThing bt = new BadThing();
bt.looselyDefinedThing = new MyCustomAttackObject();
bt.methodName = "methodThatTriggersAttack";
byte[] serializedObject = serialize(bt);
try (InputStream bis = new ByteArrayInputStream(serializedObject);
ObjectInputStream ois = new ObjectInputStream(bis)) {
ois.readObject(); // malicious code is run
}
}
private static byte[] serialize(Object object) throws Exception {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(object);
oos.flush();
return bos.toByteArray();
}
}
}

View File

@ -45,4 +45,4 @@
<providermodule.version>1.0</providermodule.version>
</properties>
</project>
</project>

View File

@ -5,3 +5,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)
- [The package-info.java File](https://www.baeldung.com/java-package-info)
- [What are Compile-time Constants in Java?](https://www.baeldung.com/java-compile-time-constants)
- [Java Objects.hash() vs Objects.hashCode()](https://www.baeldung.com/java-objects-hash-vs-objects-hashcode)

View File

@ -7,3 +7,4 @@ This module contains articles about Object-oriented programming (OOP) patterns i
- [Inheritance and Composition (Is-a vs Has-a relationship) in Java](https://www.baeldung.com/java-inheritance-composition)
- [Immutable Objects in Java](https://www.baeldung.com/java-immutable-object)
- [How to Make a Deep Copy of an Object in Java](https://www.baeldung.com/java-deep-copy)
- [Using an Interface vs. Abstract Class in Java](https://www.baeldung.com/java-interface-vs-abstract-class)

View File

@ -0,0 +1,54 @@
package com.baeldung.ignore.pattern.metacharacters;
import static org.junit.Assert.assertEquals;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.Test;
public class IgnoringPatternMetacharactersUnitTest {
private static final String dollarAmounts = "$100.25, $100.50, $150.50, $100.50, $100.75";
private static final String patternStr = "$100.50";
@Test
public void givenPatternStringHasMetacharacters_whenPatternMatchedWithoutEscapingMetacharacters_thenNoMatchesFound() {
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(dollarAmounts);
int matches = 0;
while (matcher.find()) {
matches++;
}
assertEquals(0, matches);
}
@Test
public void givenPatternStringHasMetacharacters_whenPatternCompiledUsingManuallyMetaEscapedPattern_thenMatchingSuccessful() {
String metaEscapedPatternStr = "\\Q" + patternStr + "\\E";
Pattern pattern = Pattern.compile(metaEscapedPatternStr);
Matcher matcher = pattern.matcher(dollarAmounts);
int matches = 0;
while (matcher.find()) {
matches++;
}
assertEquals(2, matches);
}
@Test
public void givenPatternStringHasMetacharacters_whenPatternCompiledUsingLiteralPatternFromQuote_thenMatchingSuccessful() {
String literalPatternStr = Pattern.quote(patternStr);
Pattern pattern = Pattern.compile(literalPatternStr);
Matcher matcher = pattern.matcher(dollarAmounts);
int matches = 0;
while (matcher.find()) {
matches++;
}
assertEquals(2, matches);
}
}

View File

@ -0,0 +1,53 @@
package com.baeldung.secretkeyandstringconversion;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Base64;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class ConversionClassUtil {
/* Generating Secret key */
// Generating Secret Key using KeyGenerator class with 256
public static SecretKey generateKey(int n) throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(n);
SecretKey originalKey = keyGenerator.generateKey();
return originalKey;
}
// Generating Secret Key using password and salt
public static SecretKey getKeyFromPassword(String password, String salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 256);
SecretKey originalKey = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
return originalKey;
}
/* Converting Secret key into String */
public static String convertSecretKeyToString(SecretKey secretKey) throws NoSuchAlgorithmException {
// Converting the Secret Key into byte array
byte[] rawData = secretKey.getEncoded();
// Getting String - Base64 encoded version of the Secret Key
String encodedKey = Base64.getEncoder().encodeToString(rawData);
return encodedKey;
}
/* Converting String into Secret key into */
public static SecretKey convertStringToSecretKeyto(String encodedKey) {
// Decoding the Base64 encoded string into byte array
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
// Rebuilding the Secret Key using SecretKeySpec Class
SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
return originalKey;
}
}

View File

@ -0,0 +1,44 @@
package com.baeldung.secretkeyandstringconversion;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.SecretKey;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class ConversionClassUtilUnitTest {
@Test
void givenPasswordAndSalt_whenCreateSecreKeyCheckConversion_thenSuccess()
throws NoSuchAlgorithmException, InvalidKeySpecException {
// given
String password = "Baeldung@2021";
String salt = "@$#baelDunG@#^$*";
// when
SecretKey encodedKey = ConversionClassUtil.getKeyFromPassword(password, salt);
String encodedString = ConversionClassUtil.convertSecretKeyToString(encodedKey);
SecretKey decodeKey = ConversionClassUtil.convertStringToSecretKeyto(encodedString);
// then
Assertions.assertEquals(encodedKey, decodeKey);
}
@Test
void givenSize_whenCreateSecreKeyCheckConversion_thenSuccess()
throws NoSuchAlgorithmException, InvalidKeySpecException {
// given
int size = 256;
// when
SecretKey encodedKey = ConversionClassUtil.generateKey(size);
String encodedString = ConversionClassUtil.convertSecretKeyToString(encodedKey);
SecretKey decodeKey = ConversionClassUtil.convertStringToSecretKeyto(encodedString);
// then
Assertions.assertEquals(encodedKey, decodeKey);
}
}

View File

@ -12,4 +12,5 @@ This module contains articles about the Stream API in Java.
- [Should We Close a Java Stream?](https://www.baeldung.com/java-stream-close)
- [Returning Stream vs. Collection](https://www.baeldung.com/java-return-stream-collection)
- [Convert a Java Enumeration Into a Stream](https://www.baeldung.com/java-enumeration-to-stream)
- [When to Use a Parallel Stream in Java](https://www.baeldung.com/java-when-to-use-parallel-stream)
- More articles: [[<-- prev>]](/../core-java-streams-2)

View File

@ -27,6 +27,17 @@
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<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>
<!-- test scoped -->
<dependency>
<groupId>org.assertj</groupId>
@ -44,11 +55,30 @@
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<lombok.version>1.18.20</lombok.version>
<!-- testing -->
<assertj.version>3.6.1</assertj.version>
<jmh.version>1.29</jmh.version>
</properties>
</project>

View File

@ -0,0 +1,9 @@
package com.baeldung.streams.parallel;
public class BenchmarkRunner {
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}
}

View File

@ -0,0 +1,54 @@
package com.baeldung.streams.parallel;
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.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class DifferentSourceSplitting {
private static final List<Integer> arrayListOfNumbers = new ArrayList<>();
private static final List<Integer> linkedListOfNumbers = new LinkedList<>();
static {
IntStream.rangeClosed(1, 1_000_000).forEach(i -> {
arrayListOfNumbers.add(i);
linkedListOfNumbers.add(i);
});
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void differentSourceArrayListSequential() {
arrayListOfNumbers.stream().reduce(0, Integer::sum);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void differentSourceArrayListParallel() {
arrayListOfNumbers.parallelStream().reduce(0, Integer::sum);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void differentSourceLinkedListSequential() {
linkedListOfNumbers.stream().reduce(0, Integer::sum);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void differentSourceLinkedListParallel() {
linkedListOfNumbers.parallelStream().reduce(0, Integer::sum);
}
}

View File

@ -0,0 +1,52 @@
package com.baeldung.streams.parallel;
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.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class MemoryLocalityCosts {
private static final int[] intArray = new int[1_000_000];
private static final Integer[] integerArray = new Integer[1_000_000];
static {
IntStream.rangeClosed(1, 1_000_000).forEach(i -> {
intArray[i-1] = i;
integerArray[i-1] = i;
});
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void localityIntArraySequential() {
Arrays.stream(intArray).reduce(0, Integer::sum);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void localityIntArrayParallel() {
Arrays.stream(intArray).parallel().reduce(0, Integer::sum);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void localityIntegerArraySequential() {
Arrays.stream(integerArray).reduce(0, Integer::sum);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void localityIntegerArrayParallel() {
Arrays.stream(integerArray).parallel().reduce(0, Integer::sum);
}
}

View File

@ -0,0 +1,52 @@
package com.baeldung.streams.parallel;
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.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class MergingCosts {
private static final List<Integer> arrayListOfNumbers = new ArrayList<>();
static {
IntStream.rangeClosed(1, 1_000_000).forEach(i -> {
arrayListOfNumbers.add(i);
});
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void mergingCostsSumSequential() {
arrayListOfNumbers.stream().reduce(0, Integer::sum);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void mergingCostsSumParallel() {
arrayListOfNumbers.stream().parallel().reduce(0, Integer::sum);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void mergingCostsGroupingSequential() {
arrayListOfNumbers.stream().collect(Collectors.toSet());
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void mergingCostsGroupingParallel() {
arrayListOfNumbers.stream().parallel().collect(Collectors.toSet());
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.streams.parallel;
import java.util.Arrays;
import java.util.List;
public class ParallelStream {
public static void main(String[] args) {
List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4);
listOfNumbers.parallelStream().forEach(number ->
System.out.println(number + " " + Thread.currentThread().getName())
);
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.streams.parallel;
import java.util.Arrays;
import java.util.List;
public class SequentialStream {
public static void main(String[] args) {
List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4);
listOfNumbers.stream().forEach(number ->
System.out.println(number + " " + Thread.currentThread().getName())
);
}
}

View File

@ -0,0 +1,27 @@
package com.baeldung.streams.parallel;
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;
import java.util.stream.IntStream;
public class SplittingCosts {
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void sourceSplittingIntStreamSequential() {
IntStream.rangeClosed(1, 100).reduce(0, Integer::sum);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public static void sourceSplittingIntStreamParallel() {
IntStream.rangeClosed(1, 100).parallel().reduce(0, Integer::sum);
}
}

View File

@ -0,0 +1,46 @@
package com.baeldung.streams.parallel;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import static org.assertj.core.api.Assertions.assertThat;
class ForkJoinUnitTest {
@Test
void givenSequentialStreamOfNumbers_whenReducingSumWithIdentityFive_thenResultIsCorrect() {
List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4);
int sum = listOfNumbers.stream().reduce(5, Integer::sum);
assertThat(sum).isEqualTo(15);
}
@Test
void givenParallelStreamOfNumbers_whenReducingSumWithIdentityFive_thenResultIsNotCorrect() {
List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4);
int sum = listOfNumbers.parallelStream().reduce(5, Integer::sum);
assertThat(sum).isNotEqualTo(15);
}
@Test
void givenParallelStreamOfNumbers_whenReducingSumWithIdentityZero_thenResultIsCorrect() {
List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4);
int sum = listOfNumbers.parallelStream().reduce(0, Integer::sum) + 5;
assertThat(sum).isEqualTo(15);
}
@Test
public void givenParallelStreamOfNumbers_whenUsingCustomThreadPool_thenResultIsCorrect()
throws InterruptedException, ExecutionException {
List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4);
ForkJoinPool customThreadPool = new ForkJoinPool(4);
int sum = customThreadPool.submit(
() -> listOfNumbers.parallelStream().reduce(0, Integer::sum)).get();
customThreadPool.shutdown();
assertThat(sum).isEqualTo(10);
}
}

View File

@ -6,4 +6,5 @@ This module contains articles about string conversions from/to another type.
- [Java String Conversions](https://www.baeldung.com/java-string-conversions)
- [Convert String to Byte Array and Reverse in Java](https://www.baeldung.com/java-string-to-byte-array)
- [Convert Character Array to String in Java](https://www.baeldung.com/java-char-array-to-string)
- [Converting String to BigDecimal in Java](https://www.baeldung.com/java-string-to-bigdecimal)
- More articles: [[<-- prev]](/core-java-string-conversions)

View File

@ -0,0 +1,74 @@
package com.baeldung.stringtobigdecimal;
import static org.junit.Assert.assertEquals;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import org.junit.Test;
public class StringToBigDecimalConversionUnitTest {
@Test
public void givenValidString_WhenBigDecimalObjectWithStringParameter_ThenResultIsDecimalObject() {
BigDecimal bigDecimal = new BigDecimal("123");
assertEquals(new BigDecimal(123), bigDecimal);
}
@Test(expected = NullPointerException.class)
public void givenNullString_WhenBigDecimalObjectWithStringParameter_ThenNullPointerExceptionIsThrown() {
String bigDecimal = null;
new BigDecimal(bigDecimal);
}
@Test(expected = NumberFormatException.class)
public void givenInalidString_WhenBigDecimalObjectWithStringParameter_ThenNumberFormatExceptionIsThrown() {
new BigDecimal("&");
}
@Test
public void givenValidString_WhenValueOfDoubleFromString_ThenResultIsDecimalObject() {
BigDecimal bigDecimal = BigDecimal.valueOf(Double.valueOf("123.42"));
assertEquals(new BigDecimal(123.42).setScale(2, BigDecimal.ROUND_HALF_UP), bigDecimal);
}
@Test(expected = NullPointerException.class)
public void givenNullString_WhenValueOfDoubleFromString_ThenNullPointerExceptionIsThrown() {
BigDecimal.valueOf(Double.valueOf(null));
}
@Test(expected = NumberFormatException.class)
public void givenInalidString_WhenValueOfDoubleFromString_ThenNumberFormatExceptionIsThrown() {
BigDecimal.valueOf(Double.valueOf("&"));
}
@Test
public void givenValidString_WhenDecimalFormatOfString_ThenResultIsDecimalObject() throws ParseException {
BigDecimal bigDecimal = new BigDecimal(10692467440017.111).setScale(3, BigDecimal.ROUND_HALF_UP);
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setGroupingSeparator(',');
symbols.setDecimalSeparator('.');
String pattern = "#,##0.0#";
DecimalFormat decimalFormat = new DecimalFormat(pattern, symbols);
decimalFormat.setParseBigDecimal(true);
// parse the string value
BigDecimal parsedStringValue = (BigDecimal) decimalFormat.parse("10,692,467,440,017.111");
assertEquals(bigDecimal, parsedStringValue);
}
@Test(expected = NullPointerException.class)
public void givenNullString_WhenDecimalFormatOfString_ThenNullPointerExceptionIsThrown() throws ParseException {
new DecimalFormat("#").parse(null);
}
@Test(expected = ParseException.class)
public void givenInalidString_WhenDecimalFormatOfString_ThenNumberFormatExceptionIsThrown() throws ParseException {
new DecimalFormat("#").parse("&");
}
}

View File

@ -3,3 +3,4 @@
- [Version Comparison in Java](https://www.baeldung.com/java-comparing-versions)
- [Java (String) or .toString()?](https://www.baeldung.com/java-string-casting-vs-tostring)
- [Split Java String by Newline](https://www.baeldung.com/java-string-split-by-newline)
- [Split a String in Java and Keep the Delimiters](https://www.baeldung.com/java-split-string-keep-delimiters)

View File

@ -0,0 +1,59 @@
package com.baeldung.splitkeepdelimiters;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test;
import com.google.common.base.Splitter;
public class SplitAndKeepDelimitersUnitTest {
private final String positivelookAheadRegex = "((?=@))";
private final String positivelookBehindRegex = "((?<=@))";
private final String positivelookAroundRegex = "((?=@)|(?<=@))";
private final String positiveLookAroundMultiDelimiterRegex = "((?=:|#|@)|(?<=:|#|@))";
private String text = "Hello@World@This@Is@A@Java@Program";
private String textMixed = "@HelloWorld@This:Is@A#Java#Program";
private String textMixed2 = "pg@no;10@hello;world@this;is@a#10words;Java#Program";
@Test
public void givenString_splitAndKeepDelimiters_using_javaLangString() {
assertThat(text.split(positivelookAheadRegex)).containsExactly("Hello", "@World", "@This", "@Is", "@A", "@Java", "@Program");
assertThat(text.split(positivelookBehindRegex)).containsExactly("Hello@", "World@", "This@", "Is@", "A@", "Java@", "Program");
assertThat(text.split(positivelookAroundRegex)).containsExactly("Hello", "@", "World", "@", "This", "@", "Is", "@", "A", "@", "Java", "@", "Program");
assertThat(textMixed.split(positiveLookAroundMultiDelimiterRegex)).containsExactly("@", "HelloWorld", "@", "This", ":", "Is", "@", "A", "#", "Java", "#", "Program");
}
@Test
public void givenString_splitAndKeepDelimiters_using_ApacheCommonsLang3StringUtils() {
assertThat(StringUtils.splitByCharacterType(textMixed2)).containsExactly("pg", "@", "no", ";", "10", "@", "hello", ";", "world", "@", "this", ";", "is", "@", "a", "#", "10", "words", ";", "J", "ava", "#", "P", "rogram");
}
@Test
public void givenString_splitAndKeepDelimiters_using_GuavaSplitter() {
assertThat(Splitter.onPattern(positivelookAroundRegex)
.splitToList(text)).containsExactly("Hello", "@", "World", "@", "This", "@", "Is", "@", "A", "@", "Java", "@", "Program");
assertThat(Splitter.on(Pattern.compile(positivelookAroundRegex))
.splitToList(text)).containsExactly("Hello", "@", "World", "@", "This", "@", "Is", "@", "A", "@", "Java", "@", "Program");
assertThat(Splitter.onPattern(positiveLookAroundMultiDelimiterRegex)
.splitToList(textMixed)).containsExactly("@", "HelloWorld", "@", "This", ":", "Is", "@", "A", "#", "Java", "#", "Program");
assertThat(Splitter.on(Pattern.compile(positiveLookAroundMultiDelimiterRegex))
.splitToList(textMixed)).containsExactly("@", "HelloWorld", "@", "This", ":", "Is", "@", "A", "#", "Java", "#", "Program");
}
}

View File

@ -1,6 +1,7 @@
<?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">
<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>
<groupId>com.example</groupId>
<artifactId>jws</artifactId>
@ -66,4 +67,4 @@
<maven-jar-plugin.version>3.0.2</maven-jar-plugin.version>
</properties>
</project>
</project>

View File

@ -1,7 +1,7 @@
<?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">
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>libraries-4</artifactId>

View File

@ -1,7 +1,7 @@
<?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">
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>libraries-5</artifactId>

View File

@ -1,7 +1,7 @@
<?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">
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>libraries-6</artifactId>
@ -112,12 +112,12 @@
<artifactId>renjin-script-engine</artifactId>
<version>${renjin.version}</version>
</dependency>
<!-- libphonenumber -->
<!-- libphonenumber -->
<dependency>
<groupId>com.googlecode.libphonenumber</groupId>
<artifactId>libphonenumber</artifactId>
<version>${libphonenumber.version}</version>
</dependency>
</dependency>
</dependencies>
<repositories>

View File

@ -21,7 +21,12 @@ public class ErrorResponseInterceptor implements Interceptor {
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);
ResponseBody originalBody = response.body();
if (originalBody != null) {
originalBody.close();
}
return response.newBuilder()
.body(responseBody)
.build();

View File

@ -1,6 +1,7 @@
<?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">
<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>libraries</artifactId>
<name>libraries</name>
@ -335,7 +336,8 @@
<configuration>
<finalName>benchmarks</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.openjdk.jmh.Main</mainClass>
</transformer>
</transformers>

View File

@ -73,8 +73,6 @@
</build>
<properties>
<!-- lombok: https://projectlombok.org/changelog.html -->
<lombok.version>1.18.10</lombok.version>
<!-- various -->
<hibernate-jpa-2.1-api.version>1.0.0.Final</hibernate-jpa-2.1-api.version>
<!-- delombok maven plugin -->

View File

@ -0,0 +1,22 @@
package com.baeldung.mapper;
import com.baeldung.dto.SimpleSource;
import com.baeldung.entity.SimpleDestination;
import com.baeldung.service.SimpleService;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.springframework.beans.factory.annotation.Autowired;
@Mapper(componentModel = "spring")
public abstract class SimpleDestinationMapperUsingInjectedService {
@Autowired
protected SimpleService simpleService;
@Mapping(target = "name", expression = "java(simpleService.enrichName(source.getName()))")
public abstract SimpleDestination sourceToDestination(SimpleSource source);
public abstract SimpleSource destinationToSource(SimpleDestination destination);
}

View File

@ -0,0 +1,11 @@
package com.baeldung.service;
import org.springframework.stereotype.Service;
@Service
public class SimpleService {
public String enrichName(String name) {
return "-:: " + name + " ::-";
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.mapper;
import com.baeldung.dto.SimpleSource;
import com.baeldung.entity.SimpleDestination;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SimpleDestinationMapperUsingInjectedIntegrationTest {
@Autowired
private SimpleDestinationMapperUsingInjectedService mapper;
@Test
public void givenSourceToDestination_whenMaps_thenNameEnriched() {
// Given
SimpleSource source = new SimpleSource();
source.setName("Bob");
source.setDescription("The Builder");
// When
SimpleDestination destination = mapper.sourceToDestination(source);
// Then
assertThat(destination).isNotNull();
assertThat(destination.getName()).isEqualTo("-:: Bob ::-");
assertThat(destination.getDescription()).isEqualTo("The Builder");
}
}

View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [Copying Files With Maven](https://www.baeldung.com/maven-copy-files)

View File

@ -0,0 +1,7 @@
## Maven Printing Plugins
This module contains articles about printing from Maven plugins.
### Relevant Articles
- [How to Display a Message in Maven](https://www.baeldung.com/maven-print-message-during-execution)

View File

@ -49,9 +49,11 @@
<goal>echo</goal>
</goals>
<configuration>
<message>Hello, world</message>
<message>Embed a line break: ${line.separator}</message>
<message>ArtifactId is ${project.artifactId}</message>
<message>
Hello, world
Embed a line break: ${line.separator}
ArtifactId is ${project.artifactId}
</message>
<level>INFO</level>
<toFile>/logs/log-echo.txt</toFile>
<append>true</append>

View File

@ -19,7 +19,6 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>io.mantisrx</groupId>
@ -35,36 +34,31 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
<dependency>
<groupId>net.andreinc.mockneat</groupId>
<artifactId>mockneat</artifactId>
<version>0.3.8</version>
<version>0.4.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<version>5.0.9.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty</artifactId>
<version>0.9.12.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>SpringLibReleaseRepo</id>
<url>https://repo.spring.io/libs-release/</url>
<id>jcenter</id>
<url>https://jcenter.bintray.com/</url>
</repository>
</repositories>

View File

@ -26,6 +26,11 @@
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>annotations</artifactId>
<version>${findbugs.annotations.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
@ -41,6 +46,7 @@
<properties>
<intellij.annotations.version>16.0.2</intellij.annotations.version>
<findbugs.annotations.version>3.0.1</findbugs.annotations.version>
<assertj-core.version>3.9.1</assertj-core.version>
</properties>

View File

@ -1,12 +1,12 @@
package com.baeldung.nulls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
public class FindBugsAnnotations {
public void accept(@NotNull Object param) {
public void accept(@NonNull Object param) {
System.out.println(param.toString());
}
@ -14,7 +14,7 @@ public class FindBugsAnnotations {
System.out.println("Printing " + param);
}
@NotNull
@NonNull
public Object process() throws Exception {
Object result = doSomething();
if (result == null) {

View File

@ -10,3 +10,4 @@ This module contains articles about the Java Persistence API (JPA) in Java.
- [JPA CascadeType.REMOVE vs orphanRemoval](https://www.baeldung.com/jpa-cascade-remove-vs-orphanremoval)
- [A Guide to MultipleBagFetchException in Hibernate](https://www.baeldung.com/java-hibernate-multiplebagfetchexception)
- [How to Convert a Hibernate Proxy to a Real Entity Object](https://www.baeldung.com/hibernate-proxy-to-real-entity-object)
- [Returning an Auto-Generated Id with JPA](https://www.baeldung.com/jpa-get-auto-generated-id)

View File

@ -68,6 +68,12 @@
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,41 @@
package com.baeldung.jpa.IdGeneration;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
// @GeneratedValue(strategy = GenerationType.SEQUENCE)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String username;
private String password;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

View File

@ -0,0 +1,19 @@
package com.baeldung.jpa.IdGeneration;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
public class UserService {
EntityManager entityManager;
public UserService(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Transactional
public long saveUser(User user){
entityManager.persist(user);
return user.getId();
}
}

View File

@ -97,4 +97,20 @@
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
</properties>
</persistence-unit>
<persistence-unit name="jpa-h2-id-generation">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.baeldung.jpa.IdGeneration.User</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:idGen"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
</properties>
</persistence-unit>
</persistence>

View File

@ -0,0 +1,47 @@
package com.baeldung.jpa.IdGeneration;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.util.UUID;
public class IdGenerationIntegrationTest {
private static EntityManager entityManager;
private static UserService service;
@BeforeClass
public static void setup() {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-h2-id-generation");
entityManager = factory.createEntityManager();
service = new UserService(entityManager);
}
@Test
public void whenNewUserIsPersisted_thenEntityHasNoId() {
User user = new User();
user.setUsername("test");
user.setPassword(UUID.randomUUID().toString());
long index = service.saveUser(user);
Assert.assertEquals(0L, index);
}
@Test
public void whenTransactionIsControlled_thenEntityHasId() {
User user = new User();
user.setUsername("test");
user.setPassword(UUID.randomUUID().toString());
entityManager.getTransaction().begin();
long index = service.saveUser(user);
entityManager.getTransaction().commit();
Assert.assertEquals(2L, index);
}
}

View File

@ -9,6 +9,7 @@ This module contains articles about annotations used in Spring Data JPA
- [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)
- [JPA Entity Lifecycle Events](https://www.baeldung.com/jpa-entity-lifecycle-events)
- [Overriding Column Definition With @AttributeOverride](https://www.baeldung.com/jpa-attributeoverride)
### Eclipse Config
After importing the project into Eclipse, you may see the following error:

View File

@ -0,0 +1,25 @@
package com.baeldung.attribute.override.entity;
import javax.persistence.Embeddable;
@Embeddable
public class Address {
private String name;
private String city;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.attribute.override.entity;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import java.time.LocalDate;
@Embeddable
public class Brand {
private String name;
private LocalDate foundationDate;
@Embedded
private Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDate getFoundationDate() {
return foundationDate;
}
public void setFoundationDate(LocalDate foundationDate) {
this.foundationDate = foundationDate;
}
}

View File

@ -0,0 +1,54 @@
package com.baeldung.attribute.override.entity;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import java.util.Map;
@Entity
@AttributeOverride(name = "identifier", column = @Column(name = "VIN"))
public class Car extends Vehicle {
private String model;
private String name;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "name", column = @Column(name = "BRAND_NAME", length = 5)),
@AttributeOverride(name = "address.name", column = @Column(name = "ADDRESS_NAME"))
})
private Brand brand;
@ElementCollection
@AttributeOverrides({
@AttributeOverride(name = "key.name", column = @Column(name = "OWNER_NAME")),
@AttributeOverride(name = "key.surname", column = @Column(name = "OWNER_SURNAME")),
@AttributeOverride(name = "value.name", column = @Column(name = "ADDRESS_NAME")),
})
Map<Owner, Address> owners;
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Brand getBrand() {
return brand;
}
public void setBrand(Brand brand) {
this.brand = brand;
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.attribute.override.entity;
import javax.persistence.Embeddable;
@Embeddable
public class Owner {
private String name;
private String surname;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}

View File

@ -0,0 +1,38 @@
package com.baeldung.attribute.override.entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
public class Vehicle {
@Id
@GeneratedValue
private Integer id;
private String identifier;
private Integer numberOfWheels;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public Integer getNumberOfWheels() {
return numberOfWheels;
}
public void setNumberOfWheels(Integer numberOfWheels) {
this.numberOfWheels = numberOfWheels;
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.attribute.override.repository;
import com.baeldung.attribute.override.entity.Car;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CarRepository extends JpaRepository<Car, Integer> {
}

View File

@ -0,0 +1,56 @@
package com.baeldung.attribute.override;
import com.baeldung.Application;
import com.baeldung.attribute.override.entity.Address;
import com.baeldung.attribute.override.entity.Brand;
import com.baeldung.attribute.override.entity.Car;
import com.baeldung.attribute.override.repository.CarRepository;
import org.assertj.core.api.Assertions;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { Application.class })
public class AttributeOverrideIntegrationTest {
private static final LocalDate FORD_FOUNDATION_DATE = LocalDate.parse("1903-06-16");
@Autowired
CarRepository carRepository;
@Test
@Transactional
public void whenInsertingCar_thenEmbeddedAndMappedFieldsArePopulated() {
Car fordMustang = createMustang();
carRepository.save(fordMustang);
Car actualCar = carRepository.getOne(fordMustang.getId());
Assertions.assertThat(actualCar).isEqualTo(fordMustang);
}
@NotNull
private Car createMustang() {
Address address = new Address();
address.setName("Ford United States");
address.setCity("Dearborn");
Brand ford = new Brand();
ford.setName("Ford");
ford.setFoundationDate(FORD_FOUNDATION_DATE);
Car fordMustang = new Car();
fordMustang.setIdentifier("WP1AB29P88LA47599");
fordMustang.setModel("Ford");
fordMustang.setName("My car");
fordMustang.setBrand(ford);
return fordMustang;
}
}

View File

@ -10,6 +10,7 @@ This module contains articles about CRUD operations in Spring Data JPA
- [Batch Insert/Update with Hibernate/JPA](https://www.baeldung.com/jpa-hibernate-batch-insert-update)
- [Difference Between save() and saveAndFlush() in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-save-saveandflush)
- [Generate Database Schema with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-generate-db-schema)
- [How to Implement a Soft Delete with Spring JPA](https://www.baeldung.com/spring-jpa-soft-delete)
### Eclipse Config
After importing the project into Eclipse, you may see the following error:

View File

@ -0,0 +1,68 @@
package com.baeldung.softdelete;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.ParamDef;
import org.hibernate.annotations.SQLDelete;
@Entity
@Table(name = "tbl_products")
@SQLDelete(sql = "UPDATE tbl_products SET deleted = true WHERE id=?")
@FilterDef(name = "deletedProductFilter", parameters = @ParamDef(name = "isDeleted", type = "boolean"))
@Filter(name = "deletedProductFilter", condition = "deleted = :isDeleted")
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
private boolean deleted = Boolean.FALSE;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public boolean isDeleted() {
return deleted;
}
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
}

View File

@ -0,0 +1,34 @@
package com.baeldung.softdelete;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductService productService;
@PostMapping
public Product createOne(@RequestBody Product product) {
return productService.create(product);
}
@DeleteMapping("/{id}")
public void removeOne(@PathVariable("id") Long id) {
productService.remove(id);
}
@GetMapping
public Iterable<Product> findAll(@RequestParam(value = "isDeleted", required = false, defaultValue = "false") boolean isDeleted) {
return productService.findAll(isDeleted);
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.softdelete;
import org.springframework.data.repository.CrudRepository;
public interface ProductRepository extends CrudRepository<Product, Long>{
}

View File

@ -0,0 +1,35 @@
package com.baeldung.softdelete;
import javax.persistence.EntityManager;
import org.hibernate.Filter;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
@Autowired
private EntityManager entityManager;
public Product create(Product product) {
return productRepository.save(product);
}
public void remove(Long id){
productRepository.deleteById(id);
}
public Iterable<Product> findAll(boolean isDeleted){
Session session = entityManager.unwrap(Session.class);
Filter filter = session.enableFilter("deletedProductFilter");
filter.setParameter("isDeleted", isDeleted);
Iterable<Product> products = productRepository.findAll();
session.disableFilter("deletedProductFilter");
return products;
}
}

View File

@ -5,10 +5,5 @@ spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true
spring.jpa.properties.hibernate.generate_statistics=true
# JPA-Schema-Generation
# Use below configuration to generate database schema create commands based on the entity models
# and export them into the create.sql file
#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create
#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql
#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-source=metadata
#spring.jpa.properties.hibernate.format_sql=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

View File

@ -1276,6 +1276,7 @@
</build>
<modules>
<module>spring-boot-modules/spring-boot-cassandre</module>
<module>core-java-modules/core-java-9</module>
<module>core-java-modules/core-java-9-improvements</module>
<module>core-java-modules/core-java-9-jigsaw</module>
@ -1404,7 +1405,7 @@
<maven-jxr-plugin.version>3.0.0</maven-jxr-plugin.version>
<!-- <maven-pmd-plugin.version>3.9.0</maven-pmd-plugin.version> -->
<maven-pmd-plugin.version>3.13.0</maven-pmd-plugin.version>
<lombok.version>1.16.12</lombok.version>
<lombok.version>1.18.20</lombok.version>
<h2.version>1.4.197</h2.version>
</properties>

View File

@ -146,7 +146,7 @@ public class WebClientLoggingIntegrationTest {
.exchange()
.block();
verify(mockAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains("domain=.typicode.com;")));
verify(mockAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains(sampleUrl)));
}

View File

@ -70,7 +70,6 @@
<module>spring-boot-swagger-jwt</module>
<module>spring-boot-testing</module>
<module>spring-boot-vue</module>
<module>spring-boot-xml</module>
<module>spring-boot-actuator</module>
<module>spring-boot-data-2</module>
<module>spring-boot-react</module>

View File

@ -60,7 +60,7 @@
</build>
<properties>
<spring-boot-admin-starter-client.version>2.4.0</spring-boot-admin-starter-client.version>
<spring-boot-admin-starter-client.version>2.4.1</spring-boot-admin-starter-client.version>
<spring-boot-maven-plugin.version>2.0.4.RELEASE</spring-boot-maven-plugin.version>
</properties>

View File

@ -76,8 +76,8 @@
</build>
<properties>
<spring-boot-admin-server.version>2.4.0</spring-boot-admin-server.version>
<spring-boot-admin-starter-client.version>2.4.0</spring-boot-admin-starter-client.version>
<spring-boot-admin-server.version>2.4.1</spring-boot-admin-server.version>
<spring-boot-admin-starter-client.version>2.4.1</spring-boot-admin-starter-client.version>
<spring-boot-admin-server-ui-login.version>1.5.7</spring-boot-admin-server-ui-login.version>
<spring-boot-maven-plugin.version>2.0.4.RELEASE</spring-boot-maven-plugin.version>
</properties>

View File

@ -5,3 +5,4 @@ This module contains articles about Spring Boot customization 2
### Relevant Articles:
- [DispatcherServlet and web.xml in Spring Boot](https://www.baeldung.com/spring-boot-dispatcherservlet-web-xml)
- [XML Defined Beans in Spring Boot](https://www.baeldung.com/spring-boot-xml-beans)

View File

@ -23,7 +23,10 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>

View File

@ -0,0 +1 @@
sample=string loaded from properties!

View File

@ -1,5 +1,6 @@
package com.baeldung.springbootxml;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;

View File

@ -0,0 +1,11 @@
# Cassandre trading bot example
This project is an example of a trading bot developed with Cassandre
## Running the examples
* `mvn test` - Run strategy backtesting
* `mvn spring-boot:run` - Run the bot
## Relevant Articles
- [Build a Trading Bot with Cassandre Spring Boot Starter](https://www.baeldung.com/cassandre-spring-boot-trading-bot)

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Cassandre trading bot tutorial</name>
<description>Cassandre trading bot tutorial</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Cassandre dependencies -->
<dependency>
<groupId>tech.cassandre.trading.bot</groupId>
<artifactId>cassandre-trading-bot-spring-boot-starter</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>org.knowm.xchange</groupId>
<artifactId>xchange-kucoin</artifactId>
<version>5.0.7</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Cassandre dependencies -->
<dependency>
<groupId>tech.cassandre.trading.bot</groupId>
<artifactId>cassandre-trading-bot-spring-boot-starter-test</artifactId>
<version>4.2.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.4.5</version>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,13 @@
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

View File

@ -0,0 +1,66 @@
package com.example.demo;
import static tech.cassandre.trading.bot.dto.position.PositionStatusDTO.CLOSED;
import static tech.cassandre.trading.bot.dto.position.PositionStatusDTO.OPENED;
import static tech.cassandre.trading.bot.dto.util.CurrencyDTO.BTC;
import static tech.cassandre.trading.bot.dto.util.CurrencyDTO.USDT;
import java.math.BigDecimal;
import java.util.Optional;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tech.cassandre.trading.bot.dto.market.TickerDTO;
import tech.cassandre.trading.bot.dto.position.PositionDTO;
import tech.cassandre.trading.bot.dto.position.PositionRulesDTO;
import tech.cassandre.trading.bot.dto.user.AccountDTO;
import tech.cassandre.trading.bot.dto.util.CurrencyPairDTO;
import tech.cassandre.trading.bot.strategy.BasicCassandreStrategy;
import tech.cassandre.trading.bot.strategy.CassandreStrategy;
@CassandreStrategy
public class MyFirstStrategy extends BasicCassandreStrategy {
private final Logger logger = LoggerFactory.getLogger(MyFirstStrategy.class);
@Override
public Set<CurrencyPairDTO> getRequestedCurrencyPairs() {
return Set.of(new CurrencyPairDTO(BTC, USDT));
}
@Override
public Optional<AccountDTO> getTradeAccount(Set<AccountDTO> accounts) {
return accounts.stream()
.filter(a -> "trade".equals(a.getName()))
.findFirst();
}
@Override
public void onTickerUpdate(TickerDTO ticker) {
logger.info("Received a new ticker : {}", ticker);
if (new BigDecimal("56000").compareTo(ticker.getLast()) == -1) {
if (canBuy(new CurrencyPairDTO(BTC, USDT), new BigDecimal("0.01"))) {
PositionRulesDTO rules = PositionRulesDTO.builder()
.stopGainPercentage(4f)
.stopLossPercentage(25f)
.build();
createLongPosition(new CurrencyPairDTO(BTC, USDT), new BigDecimal("0.01"), rules);
}
}
}
@Override
public void onPositionStatusUpdate(PositionDTO position) {
if (position.getStatus() == OPENED) {
logger.info("> New position opened : {}", position.getPositionId());
}
if (position.getStatus() == CLOSED) {
logger.info("> Position closed : {}", position.getDescription());
}
}
}

View File

@ -0,0 +1,22 @@
#
# Exchange configuration.
cassandre.trading.bot.exchange.name=kucoin
cassandre.trading.bot.exchange.username=kucoin.cassandre.test@gmail.com
cassandre.trading.bot.exchange.passphrase=cassandre
cassandre.trading.bot.exchange.key=6054ad25365ac6000689a998
cassandre.trading.bot.exchange.secret=af080d55-afe3-47c9-8ec1-4b479fbcc5e7
#
# Modes
cassandre.trading.bot.exchange.modes.sandbox=true
cassandre.trading.bot.exchange.modes.dry=false
#
# Exchange API calls rates (ms or standard ISO 8601 duration like 'PT5S').
cassandre.trading.bot.exchange.rates.account=2000
cassandre.trading.bot.exchange.rates.ticker=2000
cassandre.trading.bot.exchange.rates.trade=2000
#
# Database configuration.
cassandre.trading.bot.database.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
cassandre.trading.bot.database.datasource.url=jdbc:hsqldb:mem:cassandre
cassandre.trading.bot.database.datasource.username=sa
cassandre.trading.bot.database.datasource.password=

View File

@ -0,0 +1,13 @@
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
}
}

View File

@ -0,0 +1,55 @@
package com.example.demo;
import static org.awaitility.Awaitility.await;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static tech.cassandre.trading.bot.dto.position.PositionStatusDTO.OPENED;
import static tech.cassandre.trading.bot.dto.util.CurrencyDTO.USDT;
import java.util.HashMap;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import tech.cassandre.trading.bot.dto.util.CurrencyDTO;
import tech.cassandre.trading.bot.dto.util.GainDTO;
import tech.cassandre.trading.bot.test.mock.TickerFluxMock;
@SpringBootTest
@Import(TickerFluxMock.class)
@DisplayName("Simple strategy test")
public class MyFirstStrategyUnitTest {
private final Logger logger = LoggerFactory.getLogger(MyFirstStrategyUnitTest.class);
@Autowired
private MyFirstStrategy strategy;
@Autowired
private TickerFluxMock tickerFluxMock;
@Test
@DisplayName("Check gains")
public void whenTickersArrives_thenCheckGains() {
await().forever().until(() -> tickerFluxMock.isFluxDone());
final HashMap<CurrencyDTO, GainDTO> gains = strategy.getGains();
logger.info("Cumulated gains:");
gains.forEach((currency, gain) -> logger.info(currency + " : " + gain.getAmount()));
logger.info("Position still opened :");
strategy.getPositions()
.values()
.stream()
.filter(p -> p.getStatus().equals(OPENED))
.forEach(p -> logger.info(" - {} " + p.getDescription()));
assertTrue(gains.get(USDT).getPercentage() > 0);
}
}

View File

@ -0,0 +1,22 @@
#
# Exchange configuration.
cassandre.trading.bot.exchange.name=kucoin
cassandre.trading.bot.exchange.username=kucoin.cassandre.test@gmail.com
cassandre.trading.bot.exchange.passphrase=cassandre
cassandre.trading.bot.exchange.key=6054ad25365ac6000689a998
cassandre.trading.bot.exchange.secret=af080d55-afe3-47c9-8ec1-4b479fbcc5e7
#
# Modes
cassandre.trading.bot.exchange.modes.sandbox=true
cassandre.trading.bot.exchange.modes.dry=true
#
# Exchange API calls rates (ms or standard ISO 8601 duration like 'PT5S').
cassandre.trading.bot.exchange.rates.account=2000
cassandre.trading.bot.exchange.rates.ticker=2000
cassandre.trading.bot.exchange.rates.trade=2000
#
# Database configuration.
cassandre.trading.bot.database.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
cassandre.trading.bot.database.datasource.url=jdbc:hsqldb:mem:cassandre
cassandre.trading.bot.database.datasource.username=sa
cassandre.trading.bot.database.datasource.password=

View File

@ -0,0 +1,89 @@
1612569600 38294.4 39195.5 40964.2 38217.5 3882.29460938 153897343.463150723
1612656000 39195.4 38807.6 39623.6 37341.4 2389.96820017 91972455.834535369
1612742400 38807.6 46373.5 46767.9 38010 4971.54731481 212132648.426718929
1612828800 46374.6 46434.8 48139.3 44961 4330.72854712 201891604.027160303
1612915200 46430 44812.2 47300 43687.5 4351.84907778 198189685.592028516
1613001600 44806.1 47941.5 48647.6 44005.8 4045.91883504 188171651.974437139
1613088000 47963.1 47310.7 48958.8 46181.2 3356.01832119 159561721.419695848
1613174400 47305.4 47152.6 48120.5 46225.5 2740.99221759 129227867.922246174
1613260800 47152.5 48591.9 49686.9 47026.3 3359.4690565 163299915.839307312
1613347200 48587.2 47904.4 49003.6 42841.6 3974.98461358 188990056.26923591
1613433600 47913.1 49147.7 50619.3 47023.9 3599.85370182 176084748.845657596
1613520000 49147.7 52118.1 52609.6 48931.1 3356.85082847 170893567.530348564
1613606400 52114.3 51568.9 52522.9 50906.4 2183.18379408 113272339.172174965
1613692800 51561.1 55890.5 56317.7 50727 3749.6920105 200656740.865959032
1613779200 55893.6 55851.5 57622.6 53463.3 3394.87226216 190744601.429330887
1613865600 55851.4 57423 58336.3 55489.6 2514.02340013 143658132.671448082
1613952000 57420.6 54096.6 57517.8 44160 6125.32442907 330513978.457310237
1614038400 54085.9 48908.3 54174.2 44900 8048.96505298 389277314.445372085
1614124800 48902.9 49685.2 51361.9 47003.2 4816.75027676 239303706.844272809
1614211200 49676.5 47082.7 52019.6 46624.4 3701.80236678 184044004.383578525
1614297600 47082 46289.6 48408.8 44135 5329.77125908 247604118.914146591
1614384000 46290.2 46114.4 48381.9 44836.5 2872.64640734 134946360.020429589
1614470400 46111.3 45141.6 46626.1 43004.3 3940.17863714 175990962.484551548
1614556800 45136.5 49590.3 49771.3 44958.9 3548.51026561 169389196.772247159
1614643200 49590.3 48441.2 50201.6 47052.8 2936.94454126 142575425.463057812
1614729600 48440.6 50345.5 52623.9 48100 3177.38943911 160801620.821885745
1614816000 50347.6 48374.5 51762.1 47505.7 3624.17683614 178873453.27515484
1614902400 48374.5 48758.9 49450 46189.8 3697.34556922 176318969.507294567
1614988800 48746.9 48871.9 49255.1 47001 1949.15311354 94201823.810314647
1615075200 48885 50930.4 51424.7 48885 2444.3584982 122962479.787996993
1615161600 50956.6 52377 52387.5 49287.5 2710.99151191 137751640.241286989
1615248000 52376.9 54867.6 54867.6 51833.8 3070.93581512 165487483.114064122
1615334400 54867.5 55865.5 57364 52911.4 4049.50553851 224565244.752334892
1615420800 55863.7 57781.1 58150 54238 3403.69441456 191915265.020541521
1615507200 57781 57238.5 58057.5 55013.7 4031.0376629 228810606.091302364
1615593600 57220.7 61180.9 61815.3 56059.3 4394.62318443 259602986.875738328
1615680000 61174.3 59000 61700 59000 3084.33952274 186155667.656432156
1615766400 59000 55607.1 60632.9 54525.6 5910.33518227 338468393.188725572
1615852800 55607.1 56880.3 56918.9 53240.3 7410.49057723 409052587.523700888
1615939200 56880.3 58875.8 58951.8 54147.5 5828.79026943 328135601.648660052
1616025600 58882.9 57648.9 60107.7 57000 5073.7458698 297279816.540519693
1616112000 57648.9 58024.2 59450.1 56071 3727.09434161 217005823.723994618
1616198400 58024.3 58113.5 59874.6 57825.6 2746.52973805 161565114.165299707
1616284800 58113.5 57350.2 58591.6 55501 3265.35649781 186845535.507151609
1616371200 57345.3 54096.1 58415.5 53667 4219.99501831 237141977.003568352
1616457600 54086.8 54348.4 55823.1 52986.3 4374.34046303 239135883.538398977
1616544000 54348.4 52307.4 57200 51499.6 6416.76024581 351202326.218690674
1616630400 52307.1 51301.7 53239.1 50455 7242.6466396 375950351.557038048
1616716800 51301.7 55032 55062.5 51225.3 4609.48192944 245299757.451540308
1616803200 55031.9 55820.4 56628.6 53967.5 3634.73588532 200758048.816804103
1616889600 55820.3 55772.9 56541 54666.6 3158.20452681 176119911.151714842
1616976000 55772.8 57628.9 58400.5 54926.5 4413.63121553 251384747.301649587
1617062400 57630.8 58754.6 59351.9 57072.8 3563.87315049 208118726.050535887
1617148800 58753.2 58745.9 59800 56357.5 4921.45848213 288469053.074870873
1617235200 58745.5 58735.7 59487.1 57879 3163.98213108 186078130.901422269
1617321600 58735.7 58963.6 60179.1 58460.7 2553.76427314 151446539.609794648
1617408000 58963.6 57058.3 59795 56721.2 2512.19109578 147434403.06515736
1617494400 57052.5 58201.4 58481.2 56432.6 2069.14670128 119228330.17272614
1617580800 58201.4 59116.2 59254.1 56501 3003.76043377 174821106.684799505
1617667200 59116.2 57988.3 59497.5 57304.8 2964.86183859 173169186.845682699
1617753600 57988.3 55958.2 58668.6 55439 5277.04906389 299996660.411940246
1617840000 55958.2 58076.7 58141 55700.6 3175.60482079 181817013.517575328
1617926400 58076.7 58131.6 58900 57666.9 3516.19104669 204849717.059779284
1618012800 58138.2 59770.2 61350 57902.1 5533.50675561 332014577.538990658
1618099200 59770.2 60007.6 60687.4 59247.6 3896.37426019 233158562.799039154
1618185600 60007.6 59863.4 61270.7 59417.4 4611.409014 277430208.743380477
1618272000 59863.4 63578.7 63759.7 59815 6906.310253 430518557.569547626
1618358400 63578.7 62958.7 64840 61000 7696.509177 487298143.928065301
1618444800 62954.4 63152.6 63772.1 62023.9 4709.82427144 296178401.81115496
1618531200 63152.6 61342.6 63509.7 59930.8 8295.32523869 510423835.691643255
1618617600 61342.7 59995.2 62497.8 59599.6 5367.42979289 328364887.709585395
1618704000 59995.3 56150.6 60409.5 49001 11485.97101449 637797282.448645379
1618790400 56152.7 55618.8 57583.4 54205.2 7721.306905 432634348.931871989
1618876800 55618.7 56427.8 57061.6 53328 8677.75606016 480164200.559836543
1618963200 56426.1 53793.6 56761.7 53602 6240.82191836 345339357.806167462
1619049600 53793.5 51696.4 55474.7 50400 8879.16016304 475394174.249706678
1619136000 51691.2 51102.7 52112.1 47502.1 8885.07060366 441295812.644904319
1619222400 51109.8 50033 51157.9 48676.5 4833.41744745 241336360.887795675
1619308800 50041.5 49086.9 50554.6 46966.2 4805.34664069 237153315.222670555
1619395200 49069 54000.2 54336.4 48775.8 6695.12934907 353727728.269533971
1619481600 53997.1 55014.3 55439 53240.8 4344.22291318 237020455.905144335
1619568000 55014.2 54833.2 56399.1 53808.3 4801.04618634 262912695.604761319
1619654400 54833.1 53558.4 55181.2 52340.1 4356.05177188 234153663.397444462
1619740800 53558.5 57697.3 57936.4 53042.6 5000.47557303 277531927.921795199
1619827200 57697.3 57794.7 58471.4 57006.3 3639.78966647 210179438.189007639
1619913600 57794.7 56568.5 57903.7 56044.3 3508.52428767 199206958.05741809
1620000000 56568.5 57159.7 58977.9 56451.3 4780.43387226 276554749.540429296
1620086400 57159.7 53196.3 57188.2 53083.3 7079.55804728 390469293.396018923
1620172800 53196.3 57834.5 57979.7 52888 4224.63060355 233779565.506303973
1 1612569600 38294.4 39195.5 40964.2 38217.5 3882.29460938 153897343.463150723
2 1612656000 39195.4 38807.6 39623.6 37341.4 2389.96820017 91972455.834535369
3 1612742400 38807.6 46373.5 46767.9 38010 4971.54731481 212132648.426718929
4 1612828800 46374.6 46434.8 48139.3 44961 4330.72854712 201891604.027160303
5 1612915200 46430 44812.2 47300 43687.5 4351.84907778 198189685.592028516
6 1613001600 44806.1 47941.5 48647.6 44005.8 4045.91883504 188171651.974437139
7 1613088000 47963.1 47310.7 48958.8 46181.2 3356.01832119 159561721.419695848
8 1613174400 47305.4 47152.6 48120.5 46225.5 2740.99221759 129227867.922246174
9 1613260800 47152.5 48591.9 49686.9 47026.3 3359.4690565 163299915.839307312
10 1613347200 48587.2 47904.4 49003.6 42841.6 3974.98461358 188990056.26923591
11 1613433600 47913.1 49147.7 50619.3 47023.9 3599.85370182 176084748.845657596
12 1613520000 49147.7 52118.1 52609.6 48931.1 3356.85082847 170893567.530348564
13 1613606400 52114.3 51568.9 52522.9 50906.4 2183.18379408 113272339.172174965
14 1613692800 51561.1 55890.5 56317.7 50727 3749.6920105 200656740.865959032
15 1613779200 55893.6 55851.5 57622.6 53463.3 3394.87226216 190744601.429330887
16 1613865600 55851.4 57423 58336.3 55489.6 2514.02340013 143658132.671448082
17 1613952000 57420.6 54096.6 57517.8 44160 6125.32442907 330513978.457310237
18 1614038400 54085.9 48908.3 54174.2 44900 8048.96505298 389277314.445372085
19 1614124800 48902.9 49685.2 51361.9 47003.2 4816.75027676 239303706.844272809
20 1614211200 49676.5 47082.7 52019.6 46624.4 3701.80236678 184044004.383578525
21 1614297600 47082 46289.6 48408.8 44135 5329.77125908 247604118.914146591
22 1614384000 46290.2 46114.4 48381.9 44836.5 2872.64640734 134946360.020429589
23 1614470400 46111.3 45141.6 46626.1 43004.3 3940.17863714 175990962.484551548
24 1614556800 45136.5 49590.3 49771.3 44958.9 3548.51026561 169389196.772247159
25 1614643200 49590.3 48441.2 50201.6 47052.8 2936.94454126 142575425.463057812
26 1614729600 48440.6 50345.5 52623.9 48100 3177.38943911 160801620.821885745
27 1614816000 50347.6 48374.5 51762.1 47505.7 3624.17683614 178873453.27515484
28 1614902400 48374.5 48758.9 49450 46189.8 3697.34556922 176318969.507294567
29 1614988800 48746.9 48871.9 49255.1 47001 1949.15311354 94201823.810314647
30 1615075200 48885 50930.4 51424.7 48885 2444.3584982 122962479.787996993
31 1615161600 50956.6 52377 52387.5 49287.5 2710.99151191 137751640.241286989
32 1615248000 52376.9 54867.6 54867.6 51833.8 3070.93581512 165487483.114064122
33 1615334400 54867.5 55865.5 57364 52911.4 4049.50553851 224565244.752334892
34 1615420800 55863.7 57781.1 58150 54238 3403.69441456 191915265.020541521
35 1615507200 57781 57238.5 58057.5 55013.7 4031.0376629 228810606.091302364
36 1615593600 57220.7 61180.9 61815.3 56059.3 4394.62318443 259602986.875738328
37 1615680000 61174.3 59000 61700 59000 3084.33952274 186155667.656432156
38 1615766400 59000 55607.1 60632.9 54525.6 5910.33518227 338468393.188725572
39 1615852800 55607.1 56880.3 56918.9 53240.3 7410.49057723 409052587.523700888
40 1615939200 56880.3 58875.8 58951.8 54147.5 5828.79026943 328135601.648660052
41 1616025600 58882.9 57648.9 60107.7 57000 5073.7458698 297279816.540519693
42 1616112000 57648.9 58024.2 59450.1 56071 3727.09434161 217005823.723994618
43 1616198400 58024.3 58113.5 59874.6 57825.6 2746.52973805 161565114.165299707
44 1616284800 58113.5 57350.2 58591.6 55501 3265.35649781 186845535.507151609
45 1616371200 57345.3 54096.1 58415.5 53667 4219.99501831 237141977.003568352
46 1616457600 54086.8 54348.4 55823.1 52986.3 4374.34046303 239135883.538398977
47 1616544000 54348.4 52307.4 57200 51499.6 6416.76024581 351202326.218690674
48 1616630400 52307.1 51301.7 53239.1 50455 7242.6466396 375950351.557038048
49 1616716800 51301.7 55032 55062.5 51225.3 4609.48192944 245299757.451540308
50 1616803200 55031.9 55820.4 56628.6 53967.5 3634.73588532 200758048.816804103
51 1616889600 55820.3 55772.9 56541 54666.6 3158.20452681 176119911.151714842
52 1616976000 55772.8 57628.9 58400.5 54926.5 4413.63121553 251384747.301649587
53 1617062400 57630.8 58754.6 59351.9 57072.8 3563.87315049 208118726.050535887
54 1617148800 58753.2 58745.9 59800 56357.5 4921.45848213 288469053.074870873
55 1617235200 58745.5 58735.7 59487.1 57879 3163.98213108 186078130.901422269
56 1617321600 58735.7 58963.6 60179.1 58460.7 2553.76427314 151446539.609794648
57 1617408000 58963.6 57058.3 59795 56721.2 2512.19109578 147434403.06515736
58 1617494400 57052.5 58201.4 58481.2 56432.6 2069.14670128 119228330.17272614
59 1617580800 58201.4 59116.2 59254.1 56501 3003.76043377 174821106.684799505
60 1617667200 59116.2 57988.3 59497.5 57304.8 2964.86183859 173169186.845682699
61 1617753600 57988.3 55958.2 58668.6 55439 5277.04906389 299996660.411940246
62 1617840000 55958.2 58076.7 58141 55700.6 3175.60482079 181817013.517575328
63 1617926400 58076.7 58131.6 58900 57666.9 3516.19104669 204849717.059779284
64 1618012800 58138.2 59770.2 61350 57902.1 5533.50675561 332014577.538990658
65 1618099200 59770.2 60007.6 60687.4 59247.6 3896.37426019 233158562.799039154
66 1618185600 60007.6 59863.4 61270.7 59417.4 4611.409014 277430208.743380477
67 1618272000 59863.4 63578.7 63759.7 59815 6906.310253 430518557.569547626
68 1618358400 63578.7 62958.7 64840 61000 7696.509177 487298143.928065301
69 1618444800 62954.4 63152.6 63772.1 62023.9 4709.82427144 296178401.81115496
70 1618531200 63152.6 61342.6 63509.7 59930.8 8295.32523869 510423835.691643255
71 1618617600 61342.7 59995.2 62497.8 59599.6 5367.42979289 328364887.709585395
72 1618704000 59995.3 56150.6 60409.5 49001 11485.97101449 637797282.448645379
73 1618790400 56152.7 55618.8 57583.4 54205.2 7721.306905 432634348.931871989
74 1618876800 55618.7 56427.8 57061.6 53328 8677.75606016 480164200.559836543
75 1618963200 56426.1 53793.6 56761.7 53602 6240.82191836 345339357.806167462
76 1619049600 53793.5 51696.4 55474.7 50400 8879.16016304 475394174.249706678
77 1619136000 51691.2 51102.7 52112.1 47502.1 8885.07060366 441295812.644904319
78 1619222400 51109.8 50033 51157.9 48676.5 4833.41744745 241336360.887795675
79 1619308800 50041.5 49086.9 50554.6 46966.2 4805.34664069 237153315.222670555
80 1619395200 49069 54000.2 54336.4 48775.8 6695.12934907 353727728.269533971
81 1619481600 53997.1 55014.3 55439 53240.8 4344.22291318 237020455.905144335
82 1619568000 55014.2 54833.2 56399.1 53808.3 4801.04618634 262912695.604761319
83 1619654400 54833.1 53558.4 55181.2 52340.1 4356.05177188 234153663.397444462
84 1619740800 53558.5 57697.3 57936.4 53042.6 5000.47557303 277531927.921795199
85 1619827200 57697.3 57794.7 58471.4 57006.3 3639.78966647 210179438.189007639
86 1619913600 57794.7 56568.5 57903.7 56044.3 3508.52428767 199206958.05741809
87 1620000000 56568.5 57159.7 58977.9 56451.3 4780.43387226 276554749.540429296
88 1620086400 57159.7 53196.3 57188.2 53083.3 7079.55804728 390469293.396018923
89 1620172800 53196.3 57834.5 57979.7 52888 4224.63060355 233779565.506303973

View File

@ -0,0 +1,3 @@
BTC 1
USDT 100000
ETH 10
1 BTC 1
2 USDT 100000
3 ETH 10

View File

@ -8,6 +8,8 @@ import java.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
@Controller
public class WebController {
@ -19,6 +21,12 @@ public class WebController {
return "external";
}
@GetMapping("/logout")
public String logout(HttpServletRequest request) throws Exception {
request.logout();
return "redirect:/";
}
@GetMapping(path = "/customers")
public String customers(Principal principal, Model model) {
addCustomers();

View File

@ -27,6 +27,7 @@
</table>
<div id="pagefoot" th:include="layout :: footerFragment">Footer
</div>
<a href="/logout">Logout</a>
</div>
<!-- container -->
</body>

View File

@ -9,4 +9,5 @@ This module contains articles about Spring Web MVC in Spring Boot projects.
- [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux)
- [Differences in @Valid and @Validated Annotations in Spring](https://www.baeldung.com/spring-valid-vs-validated)
- [CharacterEncodingFilter In SpringBoot](https://www.baeldung.com/spring-boot-characterencodingfilter)
- [HandlerInterceptors vs. Filters in Spring MVC](https://www.baeldung.com/spring-mvc-handlerinterceptor-vs-filter)
- More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2)

View File

@ -0,0 +1,11 @@
package com.baeldung.filtersinterceptors;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.baeldung.filtersinterceptors")
public class FilterInterceptorApp {
public static void main(String[] args) {
SpringApplication.run(FilterInterceptorApp.class, args);
}
}

View File

@ -0,0 +1,19 @@
package com.baeldung.filtersinterceptors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloConroller {
private Logger logger = LoggerFactory.getLogger(HelloConroller.class);
@GetMapping("/hello")
public String hello() {
logger.info("Hello from the controller");
return "hello";
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.filtersinterceptors;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class LogFilter implements Filter {
private Logger logger = LoggerFactory.getLogger(LogFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
logger.info("Hello from: " + request.getLocalAddr());
chain.doFilter(request, response);
}
}

View File

@ -0,0 +1,32 @@
package com.baeldung.filtersinterceptors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class LogInterceptor implements HandlerInterceptor {
private Logger logger = LoggerFactory.getLogger(LogInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
logger.info("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
logger.info("afterCompletion");
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.filtersinterceptors;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor());
}
}

View File

@ -0,0 +1,10 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Filters vs Interceptors</title>
</head>
<body>
<h3>Hello</h3>
</body>
</html>

View File

@ -1,3 +0,0 @@
### Relevant Articles:
- [XML Defined Beans in Spring Boot](https://www.baeldung.com/spring-boot-xml-beans)

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