Merge branch 'master' into JAVA-3576
This commit is contained in:
commit
60b6c6e6b6
|
@ -44,18 +44,6 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<commons-math3.version>3.6.1</commons-math3.version>
|
||||
<io.jenetics.version>3.7.0</io.jenetics.version>
|
||||
|
|
|
@ -49,18 +49,6 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
|
|
@ -54,18 +54,6 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
|
|
@ -74,18 +74,6 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
||||
<commons-collections4.version>4.3</commons-collections4.version>
|
||||
|
|
|
@ -34,18 +34,6 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
||||
<guava.version>27.0.1-jre</guava.version>
|
||||
|
|
|
@ -49,18 +49,6 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<tradukisto.version>1.0.1</tradukisto.version>
|
||||
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
||||
|
|
|
@ -44,18 +44,6 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<commons-math3.version>3.6.1</commons-math3.version>
|
||||
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
||||
|
|
|
@ -45,18 +45,6 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<commons-math3.version>3.6.1</commons-math3.version>
|
||||
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<executable>java</executable>
|
||||
<mainClass>com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed</mainClass>
|
||||
|
@ -105,7 +104,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>run-benchmarks</id>
|
||||
|
@ -134,7 +132,6 @@
|
|||
|
||||
<properties>
|
||||
<maven-javadoc-plugin.version>3.0.0-M1</maven-javadoc-plugin.version>
|
||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||
<source.version>1.8</source.version>
|
||||
<target.version>1.8</target.version>
|
||||
</properties>
|
||||
|
|
|
@ -60,7 +60,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<executable>java</executable>
|
||||
<mainClass>com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed</mainClass>
|
||||
|
@ -108,7 +107,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
|
||||
<executions>
|
||||
<execution>
|
||||
<id>run-benchmarks</id>
|
||||
|
|
|
@ -189,7 +189,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<executable>java</executable>
|
||||
<mainClass>com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed</mainClass>
|
||||
|
@ -249,7 +248,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>run-benchmarks</id>
|
||||
|
@ -397,7 +395,6 @@
|
|||
<onejar-maven-plugin.version>1.4.4</onejar-maven-plugin.version>
|
||||
<maven-shade-plugin.version>3.1.1</maven-shade-plugin.version>
|
||||
<spring-boot-maven-plugin.version>2.0.3.RELEASE</spring-boot-maven-plugin.version>
|
||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||
<source.version>1.8</source.version>
|
||||
<target.version>1.8</target.version>
|
||||
</properties>
|
||||
|
|
|
@ -62,18 +62,6 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<commons-math3.version>3.6.1</commons-math3.version>
|
||||
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
||||
|
|
|
@ -13,3 +13,4 @@ This module contains articles about types in Java
|
|||
- [A Guide to Java Enums](https://www.baeldung.com/a-guide-to-java-enums)
|
||||
- [Determine if an Object is of Primitive Type](https://www.baeldung.com/java-object-primitive-type)
|
||||
- [Extending Enums in Java](https://www.baeldung.com/java-extending-enums)
|
||||
- [Java Class File Naming Conventions](https://www.baeldung.com/java-class-file-naming)
|
||||
|
|
|
@ -14,5 +14,4 @@ This module contains articles about networking in Java
|
|||
- [Handling java.net.ConnectException](https://www.baeldung.com/java-net-connectexception)
|
||||
- [Getting MAC addresses in Java](https://www.baeldung.com/java-mac-address)
|
||||
- [Sending Emails with Attachments in Java](https://www.baeldung.com/java-send-emails-attachments)
|
||||
- [Finding a Free Port in Java](https://www.baeldung.com/java-free-port)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-networking)
|
||||
|
|
|
@ -4,5 +4,5 @@ This module contains articles about networking in Java
|
|||
|
||||
### Relevant Articles
|
||||
|
||||
- TODO: add link once live
|
||||
- [Finding a Free Port in Java](https://www.baeldung.com/java-free-port)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-networking-2)
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
package com.baeldung.cipher;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
public class RsaUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenRsaKeyPair_whenEncryptAndDecryptString_thenCompareResults() throws Exception {
|
||||
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
|
||||
generator.initialize(2048);
|
||||
KeyPair pair = generator.generateKeyPair();
|
||||
PrivateKey privateKey = pair.getPrivate();
|
||||
PublicKey publicKey = pair.getPublic();
|
||||
|
||||
String secretMessage = "Baeldung secret message";
|
||||
Cipher encryptCipher = Cipher.getInstance("RSA");
|
||||
encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
byte[] secretMessageBytes = secretMessage.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes);
|
||||
|
||||
Cipher decryptCipher = Cipher.getInstance("RSA");
|
||||
decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
byte[] decryptedMessageBytes = decryptCipher.doFinal(encryptedMessageBytes);
|
||||
String decryptedMessage = new String(decryptedMessageBytes, StandardCharsets.UTF_8);
|
||||
|
||||
Assertions.assertEquals(secretMessage, decryptedMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRsaKeyPair_whenEncryptAndDecryptFile_thenCompareResults() throws Exception {
|
||||
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
|
||||
generator.initialize(2048);
|
||||
KeyPair pair = generator.generateKeyPair();
|
||||
PrivateKey privateKey = pair.getPrivate();
|
||||
PublicKey publicKey = pair.getPublic();
|
||||
|
||||
String originalContent = "some secret message";
|
||||
Path tempFile = Files.createTempFile("temp", "txt");
|
||||
writeString(tempFile, originalContent);
|
||||
|
||||
byte[] fileBytes = Files.readAllBytes(tempFile);
|
||||
Cipher encryptCipher = Cipher.getInstance("RSA");
|
||||
encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
byte[] encryptedFileBytes = encryptCipher.doFinal(fileBytes);
|
||||
try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) {
|
||||
stream.write(encryptedFileBytes);
|
||||
}
|
||||
|
||||
encryptedFileBytes = Files.readAllBytes(tempFile);
|
||||
Cipher decryptCipher = Cipher.getInstance("RSA");
|
||||
decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
byte[] decryptedFileBytes = decryptCipher.doFinal(encryptedFileBytes);
|
||||
try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) {
|
||||
stream.write(decryptedFileBytes);
|
||||
}
|
||||
|
||||
String fileContent = readString(tempFile);
|
||||
|
||||
Assertions.assertEquals(originalContent, fileContent);
|
||||
}
|
||||
|
||||
private void writeString(Path path, String content) throws Exception {
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(path)) {
|
||||
writer.write(content);
|
||||
}
|
||||
}
|
||||
|
||||
private String readString(Path path) throws Exception {
|
||||
StringBuilder resultStringBuilder = new StringBuilder();
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(path.toFile()))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
resultStringBuilder.append(line);
|
||||
}
|
||||
}
|
||||
return resultStringBuilder.toString();
|
||||
}
|
||||
}
|
|
@ -10,4 +10,5 @@ This module contains articles about the Stream API in Java.
|
|||
- [Debugging Java 8 Streams with IntelliJ](https://www.baeldung.com/intellij-debugging-java-streams)
|
||||
- [Add BigDecimals using the Stream API](https://www.baeldung.com/java-stream-add-bigdecimals)
|
||||
- [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)
|
||||
- More articles: [[<-- prev>]](/../core-java-streams-2)
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<executable>java</executable>
|
||||
<mainClass>com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed</mainClass>
|
||||
|
@ -68,7 +67,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
|
||||
<executions>
|
||||
<execution>
|
||||
<id>run-benchmarks</id>
|
||||
|
|
|
@ -94,7 +94,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<executable>java</executable>
|
||||
<mainClass>com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed</mainClass>
|
||||
|
@ -154,7 +153,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>run-benchmarks</id>
|
||||
|
@ -193,7 +191,6 @@
|
|||
<javamoney.moneta.version>1.1</javamoney.moneta.version>
|
||||
|
||||
<maven-javadoc-plugin.version>3.0.0-M1</maven-javadoc-plugin.version>
|
||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||
<source.version>1.8</source.version>
|
||||
<target.version>1.8</target.version>
|
||||
</properties>
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
|
||||
<module>core-java-networking</module>
|
||||
<module>core-java-networking-2</module>
|
||||
<module>core-java-networking-3</module>
|
||||
<module>core-java-nio</module>
|
||||
<module>core-java-nio-2</module>
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
|
|
@ -2,21 +2,18 @@
|
|||
<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.3.5.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>discord4j</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>discord4j</name>
|
||||
<description>Demo Discord bot using Discord4J + Spring Boot</description>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
@ -67,5 +64,9 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -2,21 +2,18 @@
|
|||
<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.0</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.baeldung.docker</groupId>
|
||||
<artifactId>docker-spring-boot-postgres</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>docker-spring-boot-postgres</name>
|
||||
<description>Demo project showing Spring Boot, PostgreSQL, and Docker</description>
|
||||
|
||||
<properties>
|
||||
<java.version>11</java.version>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
@ -44,5 +41,9 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<java.version>11</java.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -4,19 +4,19 @@
|
|||
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.3.1.RELEASE</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<groupId>com.baeldung.docker</groupId>
|
||||
<artifactId>docker</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<name>docker</name>
|
||||
<description>Demo project showing Spring Boot and Docker</description>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<java.version>11</java.version>
|
||||
|
|
|
@ -189,7 +189,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>start-server</id>
|
||||
|
@ -229,7 +228,6 @@
|
|||
<httpcore.version>4.4.13</httpcore.version>
|
||||
<httpclient.version>4.5.12</httpclient.version>
|
||||
<velocity-engine-core.version>2.2</velocity-engine-core.version>
|
||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||
<nullaway.version>0.3.0</nullaway.version>
|
||||
<plexus-compiler.version>2.8</plexus-compiler.version>
|
||||
<errorprone.version>2.1.3</errorprone.version>
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.6.0</version>
|
||||
<configuration>
|
||||
<mainClass>com.baeldung.quasar.App</mainClass>
|
||||
<workingDirectory>target/classes</workingDirectory>
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>flogger</module>
|
||||
<module>log4j</module>
|
||||
<module>log4j2</module>
|
||||
<module>logback</module>
|
||||
<module>log-mdc</module>
|
||||
<module>flogger</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
|
|
@ -20,14 +20,15 @@
|
|||
<module>maven-integration-test</module>
|
||||
<module>maven-multi-source</module>
|
||||
<module>maven-plugins</module>
|
||||
<module>maven-unused-dependencies</module>
|
||||
<module>maven-war-plugin</module>
|
||||
<module>maven-profiles</module>
|
||||
<module>maven-properties</module>
|
||||
<module>versions-maven-plugin</module>
|
||||
<module>version-collision</module>
|
||||
<!-- <module>maven-proxy</module> --> <!-- Not a maven project -->
|
||||
<module>maven-unused-dependencies</module>
|
||||
<module>maven-war-plugin</module>
|
||||
<module>optional-dependencies</module>
|
||||
<module>version-collision</module>
|
||||
<module>version-overriding-plugins</module>
|
||||
<module>versions-maven-plugin</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -102,7 +102,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec.plugin.version}</version>
|
||||
<configuration>
|
||||
<executable>java</executable>
|
||||
<arguments>
|
||||
|
@ -146,7 +145,6 @@
|
|||
<lombok.version>1.2.3</lombok.version>
|
||||
<reactor.version>3.1.6.RELEASE</reactor.version>
|
||||
<compiler.plugin.version>3.7.0</compiler.plugin.version>
|
||||
<exec.plugin.version>1.6.0</exec.plugin.version>
|
||||
<shade.plugin.version>3.1.0</shade.plugin.version>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
|
||||
- [Getting Database URL From JDBC Connection Object](https://www.baeldung.com/jdbc-get-url-from-connection)
|
||||
- [JDBC URL Format For Different Databases](https://www.baeldung.com/java-jdbc-url-format)
|
||||
- [How to Check if a Database Table Exists with JDBC](https://www.baeldung.com/jdbc-check-table-exists)
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
package com.baeldung.hibernate.lazycollection.model;
|
||||
|
||||
import org.hibernate.annotations.LazyCollection;
|
||||
import org.hibernate.annotations.LazyCollectionOption;
|
||||
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Entity;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class Branch {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
public Branch() {
|
||||
}
|
||||
public Branch(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@OneToMany(mappedBy = "mainBranch")
|
||||
@LazyCollection(LazyCollectionOption.TRUE)
|
||||
private List<Employee> mainEmployees;
|
||||
|
||||
@OneToMany(mappedBy = "subBranch")
|
||||
@LazyCollection(LazyCollectionOption.FALSE)
|
||||
private List<Employee> subEmployees;
|
||||
|
||||
@OneToMany(mappedBy = "additionalBranch")
|
||||
@LazyCollection(LazyCollectionOption.EXTRA)
|
||||
@OrderColumn(name = "order_id")
|
||||
private List<Employee> additionalEmployees;
|
||||
|
||||
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 List<Employee> getMainEmployees() {
|
||||
return mainEmployees;
|
||||
}
|
||||
|
||||
public void setMainEmployees(List<Employee> mainEmployees) {
|
||||
this.mainEmployees = mainEmployees;
|
||||
}
|
||||
|
||||
public List<Employee> getSubEmployees() {
|
||||
return subEmployees;
|
||||
}
|
||||
|
||||
public void setSubEmployees(List<Employee> subEmployees) {
|
||||
this.subEmployees = subEmployees;
|
||||
}
|
||||
|
||||
public List<Employee> getAdditionalEmployees() {
|
||||
return additionalEmployees;
|
||||
}
|
||||
|
||||
public void setAdditionalEmployees(List<Employee> additionalEmployees) {
|
||||
this.additionalEmployees = additionalEmployees;
|
||||
}
|
||||
|
||||
public void addMainEmployee(Employee employee) {
|
||||
if (this.mainEmployees == null) {
|
||||
this.mainEmployees = new ArrayList<>();
|
||||
}
|
||||
this.mainEmployees.add(employee);
|
||||
}
|
||||
|
||||
public void addSubEmployee(Employee employee) {
|
||||
if (this.subEmployees == null) {
|
||||
this.subEmployees = new ArrayList<>();
|
||||
}
|
||||
this.subEmployees.add(employee);
|
||||
}
|
||||
|
||||
public void addAdditionalEmployee(Employee employee) {
|
||||
if (this.additionalEmployees == null) {
|
||||
this.additionalEmployees = new ArrayList<>();
|
||||
}
|
||||
this.additionalEmployees.add(employee);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package com.baeldung.hibernate.lazycollection.model;
|
||||
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
public class Employee {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String address;
|
||||
|
||||
public Employee() {
|
||||
|
||||
}
|
||||
|
||||
public Employee(String name, Branch mainBranch, Branch subBranch, Branch additionalBranch) {
|
||||
this.name = name;
|
||||
this.mainBranch = mainBranch;
|
||||
this.subBranch = subBranch;
|
||||
this.additionalBranch = additionalBranch;
|
||||
}
|
||||
|
||||
@ManyToOne
|
||||
private Branch mainBranch;
|
||||
|
||||
@ManyToOne
|
||||
private Branch subBranch;
|
||||
|
||||
@ManyToOne
|
||||
private Branch additionalBranch;
|
||||
|
||||
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 String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public Branch getMainBranch() {
|
||||
return mainBranch;
|
||||
}
|
||||
|
||||
public void setMainBranch(Branch mainBranch) {
|
||||
this.mainBranch = mainBranch;
|
||||
}
|
||||
|
||||
public Branch getSubBranch() {
|
||||
return subBranch;
|
||||
}
|
||||
|
||||
public void setSubBranch(Branch subBranch) {
|
||||
this.subBranch = subBranch;
|
||||
}
|
||||
|
||||
public Branch getAdditionalBranch() {
|
||||
return additionalBranch;
|
||||
}
|
||||
|
||||
public void setAdditionalBranch(Branch additionalBranch) {
|
||||
this.additionalBranch = additionalBranch;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package com.baeldung.hibernate.lazycollection;
|
||||
|
||||
import com.baeldung.hibernate.lazycollection.model.Branch;
|
||||
import com.baeldung.hibernate.lazycollection.model.Employee;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
public class LazyCollectionIntegrationTest {
|
||||
|
||||
private static SessionFactory sessionFactory;
|
||||
|
||||
private Session session;
|
||||
|
||||
Branch branch;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeTests() {
|
||||
Configuration configuration = new Configuration().addAnnotatedClass(Branch.class)
|
||||
.addAnnotatedClass(Employee.class).setProperty("hibernate.dialect", H2Dialect.class.getName())
|
||||
.setProperty("hibernate.connection.driver_class", org.h2.Driver.class.getName())
|
||||
.setProperty("hibernate.connection.url", "jdbc:h2:mem:test")
|
||||
.setProperty("hibernate.connection.username", "sa").setProperty("hibernate.connection.password", "")
|
||||
.setProperty("hibernate.hbm2ddl.auto", "update");
|
||||
|
||||
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
|
||||
.applySettings(configuration.getProperties()).build();
|
||||
|
||||
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
|
||||
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
|
||||
branch = new Branch("Main Branch");
|
||||
|
||||
session.save(branch);
|
||||
|
||||
Employee mainEmployee1 = new Employee("main employee 1", branch, null, null);
|
||||
Employee mainEmployee2 = new Employee("main employee 2", branch, null, null);
|
||||
Employee mainEmployee3 = new Employee("main employee 3", branch, null, null);
|
||||
|
||||
session.save(mainEmployee1);
|
||||
session.save(mainEmployee2);
|
||||
session.save(mainEmployee3);
|
||||
|
||||
Employee subEmployee1 = new Employee("sub employee 1", null, branch, null);
|
||||
Employee subEmployee2 = new Employee("sub employee 2", null, branch, null);
|
||||
Employee subEmployee3 = new Employee("sub employee 3", null, branch, null);
|
||||
|
||||
session.save(subEmployee1);
|
||||
session.save(subEmployee2);
|
||||
session.save(subEmployee3);
|
||||
|
||||
Employee additionalEmployee1 = new Employee("additional employee 1", null, null, branch);
|
||||
Employee additionalEmployee2 = new Employee("additional employee 2", null, null, branch);
|
||||
Employee additionalEmployee3 = new Employee("additional employee 3", null, null, branch);
|
||||
|
||||
session.save(additionalEmployee1);
|
||||
session.save(additionalEmployee2);
|
||||
session.save(additionalEmployee3);
|
||||
|
||||
session.flush();
|
||||
session.refresh(branch);
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLazyFetching() {
|
||||
Assert.assertFalse(Hibernate.isInitialized(branch.getMainEmployees()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEagerFetching() {
|
||||
Assert.assertTrue(Hibernate.isInitialized(branch.getSubEmployees()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtraFetching() {
|
||||
Assert.assertFalse(Hibernate.isInitialized(branch.getAdditionalEmployees()));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterTests() {
|
||||
sessionFactory.close();
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import org.hibernate.cfg.Environment;
|
|||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
public class HibernateConfig {
|
||||
|
||||
private static SessionFactory sessionFactory;
|
||||
|
||||
public static SessionFactory getSessionFactory() {
|
||||
|
@ -16,12 +17,12 @@ public class HibernateConfig {
|
|||
Configuration configuration = new Configuration();
|
||||
|
||||
Properties settings = new Properties();
|
||||
settings.put(Environment.DRIVER, "com.mysql.cj.jdbc.Driver");
|
||||
settings.put(Environment.URL, "jdbc:mysql://localhost:3306/app_db?useSSL=false");
|
||||
settings.put(Environment.USER, "root");
|
||||
settings.put(Environment.PASS, "password");
|
||||
settings.put(Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect");
|
||||
settings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");
|
||||
settings.put(Environment.DRIVER, "org.h2.Driver");
|
||||
settings.put(Environment.URL, "jdbc:h2:mem:test");
|
||||
settings.put(Environment.USER, "sa");
|
||||
settings.put(Environment.PASS, "");
|
||||
settings.put(Environment.DIALECT, "org.hibernate.dialect.H2Dialect");
|
||||
settings.put(Environment.HBM2DDL_AUTO, "create-drop");
|
||||
configuration.setProperties(settings);
|
||||
|
||||
configuration.addAnnotatedClass(User.class);
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
package com.baeldung.ignorable.fields;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
public class TransientFieldUnitTest {
|
||||
|
||||
|
@ -34,18 +40,20 @@ public class TransientFieldUnitTest {
|
|||
@Test
|
||||
public void givenFieldWithTransientAnnotation_whenSerializingObject_thenFieldSerialized() throws IOException, ClassNotFoundException {
|
||||
|
||||
FileOutputStream fout = new FileOutputStream("test.obj");
|
||||
ObjectOutputStream out = new ObjectOutputStream(fout);
|
||||
out.writeObject(user);
|
||||
out.flush();
|
||||
out.close();
|
||||
try (FileOutputStream fout = new FileOutputStream("test.obj")) {
|
||||
ObjectOutputStream out = new ObjectOutputStream(fout);
|
||||
out.writeObject(user);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
FileInputStream fin = new FileInputStream("test.obj");
|
||||
ObjectInputStream in = new ObjectInputStream(fin);
|
||||
User savedUser = (User) in.readObject();
|
||||
in.close();
|
||||
try (FileInputStream fin = new FileInputStream("test.obj")) {
|
||||
ObjectInputStream in = new ObjectInputStream(fin);
|
||||
User savedUser = (User) in.readObject();
|
||||
|
||||
assertEquals(user.getCurrentDevice(), savedUser.getCurrentDevice());
|
||||
assertEquals(user.getCurrentDevice(), savedUser.getCurrentDevice());
|
||||
}
|
||||
|
||||
Files.deleteIfExists(Paths.get("test.obj"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>document</id>
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<module>java-jdbi</module>
|
||||
<module>java-jpa</module> <!-- long running -->
|
||||
<module>java-jpa-2</module> <!-- long running -->
|
||||
<module>java-jpa-3</module>
|
||||
<module>java-mongodb</module> <!-- long running -->
|
||||
<module>jnosql</module> <!-- long running -->
|
||||
<module>jooq</module>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -6,18 +6,15 @@ import com.baeldung.projection.repository.PersonRepository;
|
|||
import com.baeldung.projection.view.AddressView;
|
||||
import com.baeldung.projection.view.PersonDto;
|
||||
import com.baeldung.projection.view.PersonView;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD;
|
||||
|
||||
@DataJpaTest
|
||||
@RunWith(SpringRunner.class)
|
||||
@Sql(scripts = "/projection-insert-data.sql")
|
||||
@Sql(scripts = "/projection-clean-up-data.sql", executionPhase = AFTER_TEST_METHOD)
|
||||
public class JpaProjectionIntegrationTest {
|
||||
|
|
|
@ -5,6 +5,7 @@ This module contains articles about Spring with jOOQ
|
|||
### Relevant Articles:
|
||||
- [Spring Boot Support for jOOQ](https://www.baeldung.com/spring-boot-support-for-jooq)
|
||||
- [Introduction to jOOQ with Spring](https://www.baeldung.com/jooq-with-spring)
|
||||
- [Count Query In jOOQ](https://www.baeldung.com/jooq-count-query)
|
||||
|
||||
In order to fix the error "Plugin execution not covered by lifecycle configuration: org.jooq:jooq-codegen-maven:3.7.3:generate (execution: default, phase: generate-sources)", right-click on the error message and choose "Mark goal generated as ignore in pom.xml". Until version 1.4.x, the maven-plugin-plugin was covered by the default lifecycle mapping that ships with m2e.
|
||||
|
||||
|
|
17
pom.xml
17
pom.xml
|
@ -412,6 +412,7 @@
|
|||
<module>google-web-toolkit</module>
|
||||
<!-- <module>gradle</module> --> <!-- Not a maven project -->
|
||||
<!-- <module>gradle-5</module> --> <!-- Not a maven project -->
|
||||
<!-- <module>gradle-6</module> --> <!-- Not a maven project -->
|
||||
<!-- <module>grails</module> --> <!-- Not a maven project -->
|
||||
<module>graphql/graphql-java</module>
|
||||
<module>grpc</module>
|
||||
|
@ -614,11 +615,12 @@
|
|||
<module>spring-aop</module>
|
||||
<module>spring-apache-camel</module>
|
||||
|
||||
<module>spring-batch</module>
|
||||
<module>spring-batch-2</module>
|
||||
<module>spring-batch</module>
|
||||
<module>spring-batch-2</module>
|
||||
<module>spring-bom</module>
|
||||
<module>spring-boot-modules</module>
|
||||
<module>spring-boot-rest</module>
|
||||
<module>spring-boot-rest-2</module>
|
||||
|
||||
<module>spring-caching</module>
|
||||
|
||||
|
@ -875,6 +877,7 @@
|
|||
<module>google-web-toolkit</module>
|
||||
<!-- <module>gradle</module> --> <!-- Not a maven project -->
|
||||
<!-- <module>gradle-5</module> --> <!-- Not a maven project -->
|
||||
<!-- <module>gradle-6</module> --> <!-- Not a maven project -->
|
||||
<!-- <module>grails</module> --> <!-- Not a maven project -->
|
||||
<module>graphql/graphql-java</module>
|
||||
<module>grpc</module>
|
||||
|
@ -930,6 +933,7 @@
|
|||
<module>jooby</module>
|
||||
<module>jsf</module>
|
||||
<module>json</module>
|
||||
<module>json-2</module>
|
||||
<module>json-path</module>
|
||||
<module>jsoup</module>
|
||||
<module>jta</module>
|
||||
|
@ -1068,9 +1072,11 @@
|
|||
<module>spring-apache-camel</module>
|
||||
|
||||
<module>spring-batch</module>
|
||||
<module>spring-batch-2</module>
|
||||
<module>spring-bom</module>
|
||||
<module>spring-boot-modules</module>
|
||||
<module>spring-boot-rest</module>
|
||||
<module>spring-boot-rest-2</module>
|
||||
|
||||
<module>spring-caching</module>
|
||||
|
||||
|
@ -1089,6 +1095,7 @@
|
|||
<module>spring-data-rest</module>
|
||||
<module>spring-data-rest-querydsl</module>
|
||||
<module>spring-di</module>
|
||||
<module>spring-di-2</module>
|
||||
<module>spring-drools</module>
|
||||
|
||||
<module>spring-ejb</module>
|
||||
|
@ -1273,7 +1280,7 @@
|
|||
<!-- <module>core-java-modules/core-java-9-new-features</module> --> <!-- uses preview features, to be decided how to handle -->
|
||||
<module>core-java-modules/core-java-9-streams</module>
|
||||
<module>core-java-modules/core-java-10</module>
|
||||
<module>core-java-modules/core-java-11</module>
|
||||
<module>core-java-modules/core-java-11-2</module>
|
||||
<!-- <module>core-java-modules/core-java-12</module> --> <!-- uses preview features, to be decided how to handle -->
|
||||
<!-- <module>core-java-modules/core-java-13</module> --> <!-- uses preview features, to be decided how to handle -->
|
||||
<!-- <module>core-java-modules/core-java-14</module> --> <!-- uses preview features, to be decided how to handle -->
|
||||
|
@ -1318,6 +1325,7 @@
|
|||
<module>core-java-modules/core-java-9-streams</module>
|
||||
<module>core-java-modules/core-java-10</module>
|
||||
<module>core-java-modules/core-java-11</module>
|
||||
<module>core-java-modules/core-java-11-2</module>
|
||||
<!-- <module>core-java-modules/core-java-12</module> --> <!-- uses preview features, to be decided how to handle -->
|
||||
<!-- <module>core-java-modules/core-java-13</module> --> <!-- uses preview features, to be decided how to handle -->
|
||||
<!-- <module>core-java-modules/core-java-14</module> --> <!-- uses preview features, to be decided how to handle -->
|
||||
|
@ -1367,13 +1375,12 @@
|
|||
<!-- can't upgrade the plugin yet; as there is an issue with 2.22 no longer running all the tests-->
|
||||
<maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version>
|
||||
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||
<exec-maven-plugin.version>3.0.0</exec-maven-plugin.version>
|
||||
<java.version>1.8</java.version>
|
||||
<log4j.version>1.2.17</log4j.version>
|
||||
<esapi.version>2.2.2.0</esapi.version>
|
||||
<jmh-core.version>1.28</jmh-core.version>
|
||||
<jmh-generator.version>1.28</jmh-generator.version>
|
||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||
<maven-failsafe-plugin.version>2.21.0</maven-failsafe-plugin.version>
|
||||
<commons-io.version>2.8.0</commons-io.version>
|
||||
<commons-lang.version>2.6</commons-lang.version>
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<executable>java</executable>
|
||||
<mainClass>com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed</mainClass>
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.6.0</version>
|
||||
<configuration>
|
||||
<mainClass>com.baeldung.examples.slack.MainClass</mainClass>
|
||||
</configuration>
|
||||
|
|
|
@ -9,4 +9,5 @@ This module contains articles about reactive Spring 5
|
|||
- [Debugging Reactive Streams in Java](https://www.baeldung.com/spring-debugging-reactive-streams)
|
||||
- [Static Content in Spring WebFlux](https://www.baeldung.com/spring-webflux-static-content)
|
||||
- [Server-Sent Events in Spring](https://www.baeldung.com/spring-server-sent-events)
|
||||
- [Backpressure Mechanism in Spring WebFlux](https://www.baeldung.com/spring-webflux-backpressure)
|
||||
- More articles: [[<-- prev]](/spring-5-reactive)
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package com.baeldung.backpressure;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.BaseSubscriber;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
public class BackpressureUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenLimitRateSet_thenSplitIntoChunks() throws InterruptedException {
|
||||
Flux<Integer> limit = Flux.range(1, 25);
|
||||
|
||||
limit.limitRate(10);
|
||||
limit.subscribe(
|
||||
value -> System.out.println(value),
|
||||
err -> err.printStackTrace(),
|
||||
() -> System.out.println("Finished!!"),
|
||||
subscription -> subscription.request(15)
|
||||
);
|
||||
|
||||
StepVerifier.create(limit)
|
||||
.expectSubscription()
|
||||
.thenRequest(15)
|
||||
.expectNext(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
||||
.expectNext(11, 12, 13, 14, 15)
|
||||
.thenRequest(10)
|
||||
.expectNext(16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenRequestingChunks10_thenMessagesAreReceived() {
|
||||
Flux<Integer> request = Flux.range(1, 50);
|
||||
|
||||
request.subscribe(
|
||||
System.out::println,
|
||||
err -> err.printStackTrace(),
|
||||
() -> System.out.println("All 50 items have been successfully processed!!!"),
|
||||
subscription -> {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
System.out.println("Requesting the next 10 elements!!!");
|
||||
subscription.request(10);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
StepVerifier.create(request)
|
||||
.expectSubscription()
|
||||
.thenRequest(10)
|
||||
.expectNext(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
||||
.thenRequest(10)
|
||||
.expectNext(11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
|
||||
.thenRequest(10)
|
||||
.expectNext(21, 22, 23, 24, 25, 26, 27 , 28, 29 ,30)
|
||||
.thenRequest(10)
|
||||
.expectNext(31, 32, 33, 34, 35, 36, 37 , 38, 39 ,40)
|
||||
.thenRequest(10)
|
||||
.expectNext(41, 42, 43, 44, 45, 46, 47 , 48, 49 ,50)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCancel_thenSubscriptionFinished() {
|
||||
Flux<Integer> cancel = Flux.range(1, 10).log();
|
||||
|
||||
cancel.subscribe(new BaseSubscriber<Integer>() {
|
||||
@Override
|
||||
protected void hookOnNext(Integer value) {
|
||||
request(3);
|
||||
System.out.println(value);
|
||||
cancel();
|
||||
}
|
||||
});
|
||||
|
||||
StepVerifier.create(cancel)
|
||||
.expectNext(1, 2, 3)
|
||||
.thenCancel()
|
||||
.verify();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
### Relevant Articles:
|
||||
|
||||
- [Concurrent Test Execution in Spring 5](https://www.baeldung.com/spring-5-concurrent-tests)
|
|
@ -10,3 +10,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
|||
- [Liveness and Readiness Probes in Spring Boot](https://www.baeldung.com/spring-liveness-readiness-probes)
|
||||
- [Custom Information in Spring Boot Info Endpoint](https://www.baeldung.com/spring-boot-info-actuator-custom)
|
||||
- [Health Indicators in Spring Boot](https://www.baeldung.com/spring-boot-health-indicators)
|
||||
- [How to Enable All Endpoints in Spring Boot Actuator](https://www.baeldung.com/spring-boot-actuator-enable-endpoints)
|
||||
|
|
|
@ -17,20 +17,20 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
|||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
auth.inMemoryAuthentication()
|
||||
.withUser("user")
|
||||
.password(encoder.encode("password"))
|
||||
.roles("USER")
|
||||
.and()
|
||||
.withUser("admin")
|
||||
.password(encoder.encode("admin"))
|
||||
.roles("USER", "ADMIN");
|
||||
.withUser("user")
|
||||
.password(encoder.encode("password"))
|
||||
.roles("USER")
|
||||
.and()
|
||||
.withUser("admin")
|
||||
.password(encoder.encode("admin"))
|
||||
.roles("USER", "ADMIN");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(EndpointRequest.toAnyEndpoint())
|
||||
.authorizeRequests((requests) -> requests.anyRequest()
|
||||
.hasRole("ADMIN"));
|
||||
.authorizeRequests((requests) -> requests.anyRequest()
|
||||
.hasRole("ADMIN"));
|
||||
http.httpBasic();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,16 +21,16 @@ public class EndpointEnablingIntegrationTest {
|
|||
@WithMockUser(username = "user", password = "password", roles = "USER")
|
||||
public void givenWrongAuthentication_whenCallingActuator_thenReturns401() throws Exception {
|
||||
mockMvc.perform(get("/actuator"))
|
||||
.andExpect(status().isForbidden());
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
|
||||
public void givenProperAuthentication_whenCallingActuator_thenReturnsExpectedEndpoints() throws Exception {
|
||||
mockMvc.perform(get("/actuator"))
|
||||
.andExpect(jsonPath("$._links").exists())
|
||||
.andExpect(jsonPath("$._links.beans").exists())
|
||||
.andExpect(jsonPath("$._links.env").exists())
|
||||
.andExpect(jsonPath("$._links.shutdown").exists());
|
||||
.andExpect(jsonPath("$._links").exists())
|
||||
.andExpect(jsonPath("$._links.beans").exists())
|
||||
.andExpect(jsonPath("$._links.env").exists())
|
||||
.andExpect(jsonPath("$._links.shutdown").exists());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,3 +5,4 @@ This module contains articles about various Spring Boot libraries
|
|||
### Relevant Articles:
|
||||
|
||||
- [Background Jobs in Spring with JobRunr](https://www.baeldung.com/java-jobrunr-spring)
|
||||
- [Open API Server Implementation Using OpenAPI Generator](https://www.baeldung.com/java-openapi-generator-server)
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.baeldung.lazyinitialization;
|
|||
import com.baeldung.lazyinitialization.services.Writer;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
|
@ -20,7 +21,9 @@ public class Application {
|
|||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
ApplicationContext ctx = SpringApplication.run(Application.class, args);
|
||||
|
||||
System.out.println("Application context initialized!!!");
|
||||
|
||||
Writer writer1 = ctx.getBean("writer1", Writer.class);
|
||||
|
@ -29,4 +32,23 @@ public class Application {
|
|||
Writer writer2 = ctx.getBean("writer2", Writer.class);
|
||||
writer2.write("Second message");
|
||||
}
|
||||
|
||||
/*
|
||||
This method shows how to set lazy initialization and start the application using SpringApplicationBuilder
|
||||
*/
|
||||
private static ApplicationContext runUsingSpringApplicationBuilder(String[] args){
|
||||
return new SpringApplicationBuilder(Application.class)
|
||||
.lazyInitialization(true)
|
||||
.build(args)
|
||||
.run();
|
||||
}
|
||||
|
||||
/*
|
||||
This method shows how to set lazy initialization and start the application using SpringApplication
|
||||
*/
|
||||
private static ApplicationContext runUsingSpringApplication(String[] args){
|
||||
SpringApplication app = new SpringApplication(Application.class);
|
||||
app.setLazyInitialization(true);
|
||||
return app.run(args);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<mainClass>com.baeldung.propertyexpansion.SpringBootPropertyExpansionApp</mainClass>
|
||||
</configuration>
|
||||
|
@ -80,7 +79,6 @@
|
|||
<properties>
|
||||
<custom.property>Custom Property Value</custom.property>
|
||||
<apache-maven.version>2.7</apache-maven.version>
|
||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -34,8 +34,7 @@
|
|||
</dependencyManagement>
|
||||
|
||||
<properties>
|
||||
<spring-cloud-dependencies.version>Hoxton.SR4</spring-cloud-dependencies.version>
|
||||
<spring-boot.version>2.3.3.RELEASE</spring-boot.version>
|
||||
<spring-cloud-dependencies.version>2020.0.0</spring-cloud-dependencies.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
<module>spring-cloud-circuit-breaker</module>
|
||||
<module>spring-cloud-eureka-self-preservation</module>
|
||||
<!--<module>spring-cloud-openfeign</module>--> <!-- Fixing in JAVA-2820 -->
|
||||
<module>spring-cloud-sentinel</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
## Relevant Articles:
|
||||
|
||||
- [Dockerizing a Spring Boot Application](https://www.baeldung.com/dockerizing-spring-boot-application)
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-cloud-sentinel</artifactId>
|
||||
<name>spring-cloud-sentinel</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
<packaging>pom</packaging>
|
||||
<parent>
|
||||
<groupId>com.baeldung.spring.cloud</groupId>
|
||||
<artifactId>spring-cloud</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.csp</groupId>
|
||||
<artifactId>sentinel-core</artifactId>
|
||||
<version>1.8.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.csp</groupId>
|
||||
<artifactId>sentinel-annotation-aspectj</artifactId>
|
||||
<version>1.8.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.csp</groupId>
|
||||
<artifactId>sentinel-transport-simple-http</artifactId>
|
||||
<version>1.8.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
</project>
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.spring.cloud.sentinel;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SentinelApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SentinelApplication.class, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package com.baeldung.spring.cloud.sentinel.config;
|
||||
|
||||
import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
|
||||
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
|
||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
|
||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
|
||||
import com.alibaba.csp.sentinel.slots.system.SystemRule;
|
||||
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
public class SentinelAspectConfiguration {
|
||||
|
||||
public static final String RESOURCE_NAME = "greeting";
|
||||
|
||||
@Bean
|
||||
public SentinelResourceAspect sentinelResourceAspect() {
|
||||
return new SentinelResourceAspect();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initFlowRules();
|
||||
initDegradeRules();
|
||||
initSystemProtectionRules();
|
||||
}
|
||||
|
||||
private void initFlowRules() {
|
||||
List<FlowRule> flowRules = new ArrayList<>();
|
||||
FlowRule flowRule = new FlowRule();
|
||||
// Defined resource
|
||||
flowRule.setResource(RESOURCE_NAME);
|
||||
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
|
||||
// number of requests that QPS can pass in a second
|
||||
flowRule.setCount(1);
|
||||
flowRules.add(flowRule);
|
||||
FlowRuleManager.loadRules(flowRules);
|
||||
}
|
||||
|
||||
private void initDegradeRules() {
|
||||
List<DegradeRule> rules = new ArrayList<DegradeRule>();
|
||||
DegradeRule rule = new DegradeRule();
|
||||
rule.setResource(RESOURCE_NAME);
|
||||
rule.setCount(10);
|
||||
rule.setTimeWindow(10);
|
||||
rules.add(rule);
|
||||
DegradeRuleManager.loadRules(rules);
|
||||
}
|
||||
|
||||
private void initSystemProtectionRules() {
|
||||
List<SystemRule> rules = new ArrayList<>();
|
||||
SystemRule rule = new SystemRule();
|
||||
rule.setHighestSystemLoad(10);
|
||||
rules.add(rule);
|
||||
SystemRuleManager.loadRules(rules);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.baeldung.spring.cloud.sentinel.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.spring.cloud.sentinel.service.GreetingService;
|
||||
|
||||
@RestController
|
||||
public class GreetingController {
|
||||
|
||||
@Autowired
|
||||
private GreetingService greetingService;
|
||||
|
||||
@GetMapping("/hello")
|
||||
public String getGreeting() {
|
||||
return greetingService.getGreeting();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.spring.cloud.sentinel.service;
|
||||
|
||||
import com.alibaba.csp.sentinel.annotation.SentinelResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class GreetingService {
|
||||
|
||||
@SentinelResource(value = "greeting", fallback = "getGreetingFallback")
|
||||
public String getGreeting() {
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
public String getGreetingFallback(Throwable e) {
|
||||
e.printStackTrace();
|
||||
return "Bye world!";
|
||||
}
|
||||
|
||||
}
|
|
@ -5,4 +5,5 @@ This module contains articles about core Spring functionality
|
|||
## Relevant Articles:
|
||||
|
||||
- [Spring @Component Annotation](https://www.baeldung.com/spring-component-annotation)
|
||||
- [Solving Spring’s “not eligible for auto-proxying” Warning](https://www.baeldung.com/spring-not-eligible-for-auto-proxying)
|
||||
- More articles: [[<-- prev]](/spring-core-4)
|
||||
|
|
|
@ -40,7 +40,7 @@ public class EligibleForAutoProxyingIntegrationTest {
|
|||
|
||||
@Test
|
||||
public void givenAutowireInBeanPostProcessor_whenSpringContextInitialize_thenNotEligibleLogShouldShowAndGroupFieldPopulated() {
|
||||
List<ILoggingEvent> notEligibleEvents = memoryAppender.search("Bean 'randomIntGenerator' of type [com.baeldung.autoproxying.RandomIntGenerator] " +
|
||||
List<ILoggingEvent> notEligibleEvents = memoryAppender.search("Bean 'randomIntGenerator' of type [com.baeldung.component.autoproxying.RandomIntGenerator] " +
|
||||
"is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)");
|
||||
|
||||
assertEquals(0, notEligibleEvents.size());
|
||||
|
|
|
@ -39,7 +39,7 @@ public class NotEligibleForAutoProxyingIntegrationTest {
|
|||
|
||||
@Test
|
||||
public void givenAutowireInBeanPostProcessor_whenSpringContextInitialize_thenNotEligibleLogShouldShowAndGroupFieldNotPopulated() {
|
||||
List<ILoggingEvent> notEligibleEvents = memoryAppender.search("Bean 'randomIntGenerator' of type [com.baeldung.autoproxying.RandomIntGenerator] " +
|
||||
List<ILoggingEvent> notEligibleEvents = memoryAppender.search("Bean 'randomIntGenerator' of type [com.baeldung.component.autoproxying.RandomIntGenerator] " +
|
||||
"is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)");
|
||||
|
||||
assertEquals(1, notEligibleEvents.size());
|
||||
|
|
|
@ -108,7 +108,6 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<mainClass>com.baeldung.samples.FileCopyConfig</mainClass>
|
||||
</configuration>
|
||||
|
@ -122,7 +121,6 @@
|
|||
<javax-mail.version>1.4.7</javax-mail.version>
|
||||
<javax-activation.version>1.1.1</javax-activation.version>
|
||||
<maven-eclipse-plugin.version>2.10</maven-eclipse-plugin.version>
|
||||
<exec-maven-plugin.version>1.5.0</exec-maven-plugin.version>
|
||||
<h2.version>1.4.197</h2.version>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -14,33 +14,34 @@
|
|||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>spring-ldap</module>
|
||||
<module>spring-5-security</module>
|
||||
<module>spring-5-security-cognito</module>
|
||||
<module>spring-5-security-oauth</module>
|
||||
<module>spring-ldap</module>
|
||||
<module>spring-security-acl</module>
|
||||
<module>spring-security-auth0</module>
|
||||
<module>spring-security-web-angular/server</module>
|
||||
<module>spring-security-config</module>
|
||||
<module>spring-security-core</module>
|
||||
<module>spring-security-web-mvc</module>
|
||||
<module>spring-security-web-boot-1</module>
|
||||
<module>spring-security-web-boot-2</module>
|
||||
<module>spring-security-web-mvc-custom</module>
|
||||
<module>spring-security-web-digest-auth</module>
|
||||
<module>spring-security-ldap</module>
|
||||
<module>spring-security-web-login</module>
|
||||
<module>spring-security-web-persisted-remember-me</module>
|
||||
<module>spring-security-web-sockets</module>
|
||||
<module>spring-security-legacy-oidc</module>
|
||||
<module>spring-security-oauth2-sso</module>
|
||||
<module>spring-security-oidc</module>
|
||||
<module>spring-security-okta</module>
|
||||
<module>spring-security-saml</module>
|
||||
<module>spring-security-web-angular/server</module>
|
||||
<module>spring-security-web-boot-1</module>
|
||||
<module>spring-security-web-boot-2</module>
|
||||
<module>spring-security-web-boot-3</module>
|
||||
<module>spring-security-web-digest-auth</module>
|
||||
<module>spring-security-web-login</module>
|
||||
<module>spring-security-web-mvc-custom</module>
|
||||
<module>spring-security-web-mvc</module>
|
||||
<module>spring-security-web-persisted-remember-me</module>
|
||||
<module>spring-security-web-react</module>
|
||||
<module>spring-security-web-rest</module>
|
||||
<module>spring-security-web-rest-basic-auth</module>
|
||||
<module>spring-security-web-rest-custom</module>
|
||||
<module>spring-security-oauth2-sso</module>
|
||||
<module>spring-security-web-rest</module>
|
||||
<module>spring-security-web-sockets</module>
|
||||
<module>spring-security-web-thymeleaf</module>
|
||||
<module>spring-security-web-x509</module>
|
||||
<module>spring-session</module>
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
## Spring Boot Security MVC
|
||||
|
||||
This module contains articles about Spring Security with Spring MVC in Boot applications
|
||||
|
||||
### The Course
|
||||
The "REST With Spring" Classes: http://github.learnspringsecurity.com
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- [TLS Setup in Spring](https://www.baeldung.com/spring-tls-setup)
|
||||
- More articles: [[<-- prev]](/spring-security-modules/spring-security-web-boot-2)
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-security-web-boot-3</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>spring-security-web-boot-3</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Spring Security MVC Boot - 3</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-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,16 @@
|
|||
package com.baeldung.tls;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@Controller
|
||||
public class HomeController {
|
||||
|
||||
@GetMapping("/baeldung")
|
||||
public ResponseEntity<String> welcome() {
|
||||
return new ResponseEntity<>("tls/baeldung", HttpStatus.OK);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.baeldung.tls;
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests()
|
||||
.antMatchers("/**")
|
||||
.permitAll();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.tls;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
@SpringBootApplication
|
||||
public class TLSEnabledApplication {
|
||||
|
||||
public static void main(String... args) {
|
||||
SpringApplication application = new SpringApplication(TLSEnabledApplication.class);
|
||||
application.setAdditionalProfiles("tls");
|
||||
application.run(args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
server.port=8443
|
||||
|
||||
# enable/disable https
|
||||
server.ssl.enabled=true
|
||||
# keystore format
|
||||
server.ssl.key-store-type=PKCS12
|
||||
# keystore location
|
||||
server.ssl.key-store=classpath:keystore/keystore.p12
|
||||
# keystore password
|
||||
server.ssl.key-store-password=changeit
|
||||
server.ssl.key-alias=baeldung
|
||||
# SSL protocol to use
|
||||
server.ssl.protocol=TLS
|
||||
# Enabled SSL protocols
|
||||
server.ssl.enabled-protocols=TLSv1.2
|
||||
|
||||
#server.ssl.client-auth=need
|
||||
|
||||
#trust store location
|
||||
#server.ssl.trust-store=classpath:keystore/truststore.p12
|
||||
#trust store password
|
||||
#server.ssl.trust-store-password=changeit
|
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIExzCCAq+gAwIBAgIEbh/WszANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDEwls
|
||||
b2NhbGhvc3QwHhcNMjEwMzIxMDgzMzU3WhcNMzEwMzE5MDgzMzU3WjAUMRIwEAYD
|
||||
VQQDEwlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCD
|
||||
QWvAEewDE+vFFqYPgXFJ94bMgPZT6qdb17DkWWbL2jV5QENbSYTLAPNQ1TGUgKhj
|
||||
t1LCHpooLwWIo6xvhK/qZYjh3YonSIe8Eo0fBCDoZpLO+Vp0us22NBgLOYH8hvAm
|
||||
zEvPXdSZo5Qkeaqjwd6kB/z083y8OL+Civ0ARXoLsn7CFslKfZp2o/aebH6i/T+3
|
||||
hWVqasIIMtfNUrxE/pnOnV8aSAt24jcm/VxbtheqIzmcOPlCXSP1RAmFez6tJsNu
|
||||
2dbUhaeOf95RCaM6a43soEvLvooGa/uqBPsRojg5WEFGf7Tc7pzB+BtALwRmHAqr
|
||||
hiYjVv329QGZ+g8dADBvvqvGpGysy+X0LxixvIP14KdCqG8uMYmw5cBTJHc23AHV
|
||||
iP+JsfDtdu+bzZeOZmhSsv4M3DZ1QPHEX+zCnotE+SeycqEr+3SaJELyjCB1twFT
|
||||
pCRCQGWFKYCRwhjQ1vGY7qhD6ZDn30a96xAlPS+T35pA01rNgORJi8j9sf3oiwEe
|
||||
oPQOecgFHdua5drHJ78j7MUz/Gvj02GnwKnBKbMYDGeBKJWm0ir4MxoU7HPaDwLj
|
||||
jofXgIz+CMXkp+9arVu5IsZwL2MKNZ4fiM+VWZg9R73CAVpKvs6dTlQXe++DCaOr
|
||||
XGiQeCPPpIC74vqWhAHuzPncGJndHlmXYGLhi0sk0wIDAQABoyEwHzAdBgNVHQ4E
|
||||
FgQUhW4a3uWREJoTxodyD5u7i7mCaacwDQYJKoZIhvcNAQELBQADggIBAD/Qfkot
|
||||
qklQr4r7eoHtyFCGozfZvsPwEediZORkycU/fCZozdVh95ebt2/N/jw7RlNhv+t+
|
||||
HahMoiXbLX2RUrqM/2X5U7BbxIpy3XjhcEYTJudqFfCxDQfxD1bFrWHygQzAanOb
|
||||
sPHkcEt3tu2suV2YsJpHry/1BMo83WAoTgw/3dFtJ7oEoi/LaI03v9Qlp0+hLfA5
|
||||
zwyuuRqFn24FRvdWHX5GqAweF+WUdmmlkiJiKu2RtQsPoN7ITvZQs9t4l0zZ8w2v
|
||||
QV0YdhWYLkS3g53oyOP8T5YlCFGuUOyo433hRyrzaxj3aFDkMbNrX9REB9v8Iz7X
|
||||
aFsmLDJsfT5Spovz68HCIMDW1Sl1WqVkNN2V3Rwt72bn7DEbKZzGW9RC5eXEW1Zw
|
||||
46XeYOVdEjzl/l623moWC5ZTlwPF1qRDaoZXT/1d1eAJE8ZBHm1YjwgDD5aFvylG
|
||||
0OT1qWD5gx3nOmAbBk1e3r8ESMo9k29/4hycUUUgtFuWtBwBaY/O/4YoLx59wbpL
|
||||
rFR/zjKIdYFj0AM2ABTgrG7v5pEhjLTnzjc+mZV7hJCBvB+bbC5vvfDg0K7lQUpJ
|
||||
ruIPvqKfJyuTwkKmoTF5jmG04jwUDtA5iGUB3U3QiQ8zcbTiVRptXLEQDYw/bzDk
|
||||
0fd4xTbok1ygI7wJ/KRyMvFXdbTKSvVu/tnM
|
||||
-----END CERTIFICATE-----
|
Binary file not shown.
|
@ -41,6 +41,7 @@
|
|||
<module>spring-thymeleaf</module>
|
||||
<module>spring-thymeleaf-2</module>
|
||||
<module>spring-thymeleaf-3</module>
|
||||
<module>spring-boot-jsp</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
### Relevant Articles:
|
||||
|
||||
- [Spring Boot With JavaServer Pages (JSP)](https://www.baeldung.com/spring-boot-jsp)
|
|
@ -0,0 +1,91 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-boot-jsp</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>spring-boot-jsp</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-web-modules</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>${jstl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-jasper</artifactId>
|
||||
<!--uncomment below if deploying in web container-->
|
||||
<!--<scope>provided</scope>-->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<!--uncomment below if deploying in web container-->
|
||||
<!--<dependency>-->
|
||||
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||
<!-- <artifactId>spring-boot-starter-tomcat</artifactId>-->
|
||||
<!-- <scope>provided</scope>-->
|
||||
<!--</dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>spring-boot-jsp</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<configuration>
|
||||
<mainClass>com.baeldung.boot.jsp.SpringBootJspApplication</mainClass>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<jstl.version>1.2</jstl.version>
|
||||
<junit-jupiter.version>5.7.1</junit-jupiter.version>
|
||||
<spring-boot.version>2.4.4</spring-boot.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.boot.jsp;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
|
||||
@SpringBootApplication(scanBasePackages = "com.baeldung.boot.jsp")
|
||||
public class SpringBootJspApplication extends SpringBootServletInitializer {
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
|
||||
return builder.sources(SpringBootJspApplication.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpringBootJspApplication.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.baeldung.boot.jsp;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.baeldung.boot.jsp.repository.BookRepository;
|
||||
import com.baeldung.boot.jsp.repository.impl.InMemoryBookRepository;
|
||||
import com.baeldung.boot.jsp.repository.model.BookData;
|
||||
|
||||
@Configuration
|
||||
public class SpringBootJspConfiguration {
|
||||
|
||||
@Bean
|
||||
public BookRepository provideBookRepository() {
|
||||
return new InMemoryBookRepository(initialBookData());
|
||||
}
|
||||
|
||||
private static Map<String, BookData> initialBookData() {
|
||||
Map<String, BookData> initData = new HashMap<>();
|
||||
initData.put("ISBN-1", new BookData("ISBN-1", "Book 1", "Book 1 Author"));
|
||||
initData.put("ISBN-2", new BookData("ISBN-2", "Book 2", "Book 2 Author"));
|
||||
initData.put("ISBN-3", new BookData("ISBN-3", "Book 3", "Book 3 Author"));
|
||||
return initData;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package com.baeldung.boot.jsp.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
import com.baeldung.boot.jsp.dto.Book;
|
||||
import com.baeldung.boot.jsp.service.BookService;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/book")
|
||||
public class BookController {
|
||||
|
||||
private final BookService bookService;
|
||||
|
||||
public BookController(BookService bookService) {
|
||||
this.bookService = bookService;
|
||||
}
|
||||
|
||||
@GetMapping("/viewBooks")
|
||||
public String viewBooks(Model model) {
|
||||
model.addAttribute("books", bookService.getBooks());
|
||||
return "view-books";
|
||||
}
|
||||
|
||||
@GetMapping("/addBook")
|
||||
public String addBookView(Model model) {
|
||||
model.addAttribute("book", new Book());
|
||||
return "add-book";
|
||||
}
|
||||
|
||||
@PostMapping("/addBook")
|
||||
public RedirectView addBook(@ModelAttribute("book") Book book, RedirectAttributes redirectAttributes) {
|
||||
final RedirectView redirectView = new RedirectView("/book/addBook", true);
|
||||
Book savedBook = bookService.addBook(book);
|
||||
redirectAttributes.addFlashAttribute("savedBook", savedBook);
|
||||
redirectAttributes.addFlashAttribute("addBookSuccess", true);
|
||||
return redirectView;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.boot.jsp.dto;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ToString
|
||||
public class Book {
|
||||
private String isbn;
|
||||
private String name;
|
||||
private String author;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.boot.jsp.exception;
|
||||
|
||||
import com.baeldung.boot.jsp.dto.Book;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class DuplicateBookException extends RuntimeException {
|
||||
private final Book book;
|
||||
|
||||
public DuplicateBookException(Book book) {
|
||||
this.book = book;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.boot.jsp.exception;
|
||||
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@ControllerAdvice
|
||||
public class LibraryControllerAdvice {
|
||||
|
||||
@ExceptionHandler(value = DuplicateBookException.class)
|
||||
public ModelAndView duplicateBookException(DuplicateBookException e) {
|
||||
final ModelAndView modelAndView = new ModelAndView();
|
||||
modelAndView.addObject("ref", e.getBook().getIsbn());
|
||||
modelAndView.addObject("object", e.getBook());
|
||||
modelAndView.addObject("message", "Cannot add an already existing book");
|
||||
modelAndView.setViewName("error-book");
|
||||
return modelAndView;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.boot.jsp.repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.baeldung.boot.jsp.repository.model.BookData;
|
||||
|
||||
public interface BookRepository {
|
||||
Collection<BookData> findAll();
|
||||
|
||||
Optional<BookData> findById(String isbn);
|
||||
|
||||
BookData add(BookData book);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.baeldung.boot.jsp.repository.impl;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.baeldung.boot.jsp.repository.BookRepository;
|
||||
import com.baeldung.boot.jsp.repository.model.BookData;
|
||||
|
||||
public class InMemoryBookRepository implements BookRepository {
|
||||
|
||||
private final Map<String, BookData> storedBooks;
|
||||
|
||||
public InMemoryBookRepository(Map<String, BookData> storedBooks) {
|
||||
this.storedBooks = new HashMap<>();
|
||||
this.storedBooks.putAll(storedBooks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<BookData> findAll() {
|
||||
if (storedBooks.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return storedBooks.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BookData> findById(String isbn) {
|
||||
return Optional.ofNullable(storedBooks.get(isbn));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BookData add(BookData book) {
|
||||
storedBooks.put(book.getIsbn(), book);
|
||||
return book;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.baeldung.boot.jsp.repository.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class BookData {
|
||||
private String isbn;
|
||||
private String name;
|
||||
private String author;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.boot.jsp.service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.baeldung.boot.jsp.dto.Book;
|
||||
|
||||
public interface BookService {
|
||||
Collection<Book> getBooks();
|
||||
|
||||
Book addBook(Book book);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package com.baeldung.boot.jsp.service.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.baeldung.boot.jsp.exception.DuplicateBookException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baeldung.boot.jsp.dto.Book;
|
||||
import com.baeldung.boot.jsp.repository.BookRepository;
|
||||
import com.baeldung.boot.jsp.repository.model.BookData;
|
||||
import com.baeldung.boot.jsp.service.BookService;
|
||||
|
||||
@Service
|
||||
public class BookServiceImpl implements BookService {
|
||||
|
||||
private final BookRepository bookRepository;
|
||||
|
||||
public BookServiceImpl(BookRepository bookRepository) {
|
||||
this.bookRepository = bookRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Book> getBooks() {
|
||||
return bookRepository.findAll()
|
||||
.stream()
|
||||
.map(BookServiceImpl::convertBookData)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Book addBook(Book book) {
|
||||
final Optional<BookData> existingBook = bookRepository.findById(book.getIsbn());
|
||||
if (existingBook.isPresent()) {
|
||||
throw new DuplicateBookException(book);
|
||||
}
|
||||
|
||||
final BookData savedBook = bookRepository.add(convertBook(book));
|
||||
return convertBookData(savedBook);
|
||||
}
|
||||
|
||||
private static Book convertBookData(BookData bookData) {
|
||||
return new Book(bookData.getIsbn(), bookData.getName(), bookData.getAuthor());
|
||||
}
|
||||
|
||||
private static BookData convertBook(Book book) {
|
||||
return new BookData(book.getIsbn(), book.getName(), book.getAuthor());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
server.servlet.context-path=/spring-boot-jsp
|
||||
|
||||
spring.mvc.view.prefix: /WEB-INF/jsp/
|
||||
spring.mvc.view.suffix: .jsp
|
|
@ -0,0 +1,10 @@
|
|||
table {
|
||||
font-family: arial, sans-serif;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td, th {
|
||||
border: 1px solid #dddddd;
|
||||
text-align: left;
|
||||
padding: 8px;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Error</title>
|
||||
</head>
|
||||
<body>
|
||||
Opps! 4xx Error Occurred.
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,21 @@
|
|||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<html>
|
||||
<head>
|
||||
<title>Add Book</title>
|
||||
</head>
|
||||
<body>
|
||||
<c:if test="${addBookSuccess}">
|
||||
<div>Successfully added Book with ISBN: ${savedBook.isbn}</div>
|
||||
</c:if>
|
||||
|
||||
<c:url var="add_book_url" value="/book/addBook"/>
|
||||
<form:form action="${add_book_url}" method="post" modelAttribute="book">
|
||||
<form:label path="isbn">ISBN: </form:label> <form:input type="text" path="isbn"/>
|
||||
<form:label path="name">Book Name: </form:label> <form:input type="text" path="name"/>
|
||||
<form:label path="author">Author Name: </form:label> <form:input path="author"/>
|
||||
<input type="submit" value="submit"/>
|
||||
</form:form>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
<%--
|
||||
Created by IntelliJ IDEA.
|
||||
User: jason
|
||||
Date: 3/13/21
|
||||
Time: 10:39 PM
|
||||
To change this template use File | Settings | File Templates.
|
||||
--%>
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<html>
|
||||
<head>
|
||||
<title>Error</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Reference: ${ref}</p>
|
||||
<p>Error Message: ${message}</p>
|
||||
<p>Object: ${object}</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<html>
|
||||
<head>
|
||||
<title>View Books</title>
|
||||
<link href="<c:url value="/css/common.css"/>" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ISBN</th>
|
||||
<th>Name</th>
|
||||
<th>Author</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<c:forEach items="${books}" var="book">
|
||||
<tr>
|
||||
<td>${book.isbn}</td>
|
||||
<td>${book.name}</td>
|
||||
<td>${book.author}</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,93 @@
|
|||
package com.baeldung.boot.jsp.controller;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasProperty;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.ResultActions;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import com.baeldung.boot.jsp.repository.BookRepository;
|
||||
import com.baeldung.boot.jsp.repository.impl.InMemoryBookRepository;
|
||||
import com.baeldung.boot.jsp.repository.model.BookData;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
@AutoConfigureMockMvc
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class BookControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private BookRepository bookRepository;
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
public void whenAddBook_thenBookSaved() throws Exception {
|
||||
MockHttpServletRequestBuilder addBookRequest = MockMvcRequestBuilders.post("/book/addBook")
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.param("isbn", "isbn1")
|
||||
.param("name", "name1")
|
||||
.param("author", "author1");
|
||||
mockMvc.perform(addBookRequest)
|
||||
.andReturn();
|
||||
|
||||
Optional<BookData> storedBookOpt = bookRepository.findById("isbn1");
|
||||
assertTrue(storedBookOpt.isPresent());
|
||||
assertEquals("name1", storedBookOpt.get()
|
||||
.getName());
|
||||
assertEquals("author1", storedBookOpt.get()
|
||||
.getAuthor());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
public void givenAlreadyExistingBook_whenAddBook_thenShowErrorPage() throws Exception {
|
||||
MockHttpServletRequestBuilder addBookRequest = MockMvcRequestBuilders.post("/book/addBook")
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.param("isbn", "isbn1")
|
||||
.param("name", "name1")
|
||||
.param("author", "author1");
|
||||
ResultActions addBookResult = mockMvc.perform(addBookRequest);
|
||||
|
||||
addBookResult.andExpect(view().name("error-book"))
|
||||
.andExpect(model().attribute("ref", "isbn1"))
|
||||
.andExpect(model().attribute("object", hasProperty("isbn", equalTo("isbn1"))))
|
||||
.andExpect(model().attribute("message", "Cannot add an already existing book"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("com.baeldung.boot.jsp")
|
||||
static class ContextConfiguration {
|
||||
|
||||
@Bean
|
||||
public BookRepository provideBookRepository() {
|
||||
return new InMemoryBookRepository(Collections.emptyMap());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package com.baeldung.boot.jsp.controller;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.AdditionalAnswers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.ResultActions;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import com.baeldung.boot.jsp.dto.Book;
|
||||
import com.baeldung.boot.jsp.service.BookService;
|
||||
|
||||
@WebMvcTest(BookController.class)
|
||||
class BookControllerUnitTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@MockBean
|
||||
private BookService bookService;
|
||||
|
||||
@Test
|
||||
public void whenViewBooks_thenReturnBooksView() throws Exception {
|
||||
when(bookService.getBooks()).thenReturn(existingBooks());
|
||||
ResultActions viewBooksResult = mockMvc.perform(get("/book/viewBooks"));
|
||||
|
||||
viewBooksResult.andExpect(view().name("view-books"))
|
||||
.andExpect(model().attribute("books", hasSize(3)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAddBookView_thenReturnAddBooksView() throws Exception {
|
||||
ResultActions addBookViewResult = mockMvc.perform(get("/book/addBook"));
|
||||
|
||||
addBookViewResult.andExpect(view().name("add-book"))
|
||||
.andExpect(model().attribute("book", isA(Book.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAddBookPost_thenRedirectToAddBookView() throws Exception {
|
||||
when(bookService.addBook(any(Book.class))).thenAnswer(AdditionalAnswers.returnsFirstArg());
|
||||
MockHttpServletRequestBuilder addBookRequest = MockMvcRequestBuilders.post("/book/addBook")
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.param("isbn", "isbn1")
|
||||
.param("name", "name1")
|
||||
.param("author", "author1");
|
||||
ResultActions addBookResult = mockMvc.perform(addBookRequest);
|
||||
|
||||
addBookResult.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("/book/addBook"))
|
||||
.andExpect(flash().attribute("savedBook", hasProperty("isbn", equalTo("isbn1"))))
|
||||
.andExpect(flash().attribute("addBookSuccess", true));
|
||||
}
|
||||
|
||||
private static Collection<Book> existingBooks() {
|
||||
List<Book> books = new ArrayList<>();
|
||||
books.add(new Book("isbn1", "name1", "author1"));
|
||||
books.add(new Book("isbn2", "name2", "author2"));
|
||||
books.add(new Book("isbn3", "name3", "author3"));
|
||||
return books;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.baeldung.boot.jsp.repository.impl;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.boot.jsp.repository.BookRepository;
|
||||
import com.baeldung.boot.jsp.repository.model.BookData;
|
||||
|
||||
public class InMemoryBookRepositoryUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenEmtpyData_whenFindAll_thenReturnEmptyCollection() {
|
||||
BookRepository bookRepository = new InMemoryBookRepository(Collections.emptyMap());
|
||||
Collection<BookData> storedBooks = bookRepository.findAll();
|
||||
|
||||
assertEquals(0, storedBooks.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInitialData_whenFindAll_thenReturnInitialData() {
|
||||
BookRepository bookRepository = new InMemoryBookRepository(initialBookData());
|
||||
Collection<BookData> storedBooks = bookRepository.findAll();
|
||||
|
||||
assertEquals(3, storedBooks.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInitialData_whenFindUnavailableIsbn_thenReturnEmpty() {
|
||||
BookRepository bookRepository = new InMemoryBookRepository(initialBookData());
|
||||
Optional<BookData> storedBookOpt = bookRepository.findById("isbn4");
|
||||
|
||||
assertFalse(storedBookOpt.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInitialData_whenFindAvailableIsbn_thenReturnItem() {
|
||||
BookRepository bookRepository = new InMemoryBookRepository(initialBookData());
|
||||
Optional<BookData> storedBookOpt = bookRepository.findById("isbn1");
|
||||
|
||||
assertTrue(storedBookOpt.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAddedIsbn_whenFindAvailableIsbn_thenReturnItem() {
|
||||
BookRepository bookRepository = new InMemoryBookRepository(Collections.emptyMap());
|
||||
bookRepository.add(new BookData("isbn4", "name4", "author4"));
|
||||
Optional<BookData> storedBookOpt = bookRepository.findById("isbn4");
|
||||
|
||||
assertTrue(storedBookOpt.isPresent());
|
||||
}
|
||||
|
||||
private static Map<String, BookData> initialBookData() {
|
||||
Map<String, BookData> initData = new HashMap<>();
|
||||
initData.put("isbn1", new BookData("isbn1", "name1", "author1"));
|
||||
initData.put("isbn2", new BookData("isbn2", "name2", "author2"));
|
||||
initData.put("isbn3", new BookData("isbn3", "name3", "author3"));
|
||||
return initData;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package com.baeldung.boot.jsp.service;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
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.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
|
||||
import com.baeldung.boot.jsp.dto.Book;
|
||||
import com.baeldung.boot.jsp.exception.DuplicateBookException;
|
||||
import com.baeldung.boot.jsp.repository.BookRepository;
|
||||
import com.baeldung.boot.jsp.repository.impl.InMemoryBookRepository;
|
||||
import com.baeldung.boot.jsp.repository.model.BookData;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
||||
public class BookServiceIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private BookService bookService;
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
public void givenNoAddedBooks_whenGetAllBooks_thenReturnInitialBooks() {
|
||||
Collection<Book> storedBooks = bookService.getBooks();
|
||||
|
||||
assertEquals(3, storedBooks.size());
|
||||
assertThat(storedBooks, hasItem(hasProperty("isbn", equalTo("ISBN-TEST-1"))));
|
||||
assertThat(storedBooks, hasItem(hasProperty("isbn", equalTo("ISBN-TEST-2"))));
|
||||
assertThat(storedBooks, hasItem(hasProperty("isbn", equalTo("ISBN-TEST-3"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
public void givenBookNotAlreadyExists_whenAddBook_thenReturnSuccessfully() {
|
||||
Book bookToBeAdded = new Book("ISBN-ADD-TEST-4", "Added Book 4", "Added Book 4 Author");
|
||||
Book storedBook = bookService.addBook(bookToBeAdded);
|
||||
|
||||
assertEquals(bookToBeAdded.getIsbn(), storedBook.getIsbn());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
public void givenBookAlreadyExists_whenAddBook_thenDuplicateBookException() {
|
||||
Book bookToBeAdded = new Book("ISBN-ADD-TEST-4", "Updated Book 4", "Updated Book 4 Author");
|
||||
|
||||
assertThrows(DuplicateBookException.class, () -> bookService.addBook(bookToBeAdded));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("com.baeldung.boot.jsp")
|
||||
static class ContextConfiguration {
|
||||
|
||||
@Bean
|
||||
public BookRepository provideBookRepository() {
|
||||
return new InMemoryBookRepository(initialBookData());
|
||||
}
|
||||
|
||||
private static Map<String, BookData> initialBookData() {
|
||||
Map<String, BookData> initData = new HashMap<>();
|
||||
initData.put("ISBN-TEST-1", new BookData("ISBN-TEST-1", "Book 1", "Book 1 Author"));
|
||||
initData.put("ISBN-TEST-2", new BookData("ISBN-TEST-2", "Book 2", "Book 2 Author"));
|
||||
initData.put("ISBN-TEST-3", new BookData("ISBN-TEST-3", "Book 3", "Book 3 Author"));
|
||||
return initData;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package com.baeldung.boot.jsp.service.impl;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.AdditionalAnswers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import com.baeldung.boot.jsp.dto.Book;
|
||||
import com.baeldung.boot.jsp.exception.DuplicateBookException;
|
||||
import com.baeldung.boot.jsp.repository.BookRepository;
|
||||
import com.baeldung.boot.jsp.repository.model.BookData;
|
||||
import com.baeldung.boot.jsp.service.BookService;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class BookServiceImplUnitTest {
|
||||
|
||||
@Mock
|
||||
private BookRepository bookRepository;
|
||||
|
||||
@Test
|
||||
public void whenGetBooks_thenAllBooksReturned() {
|
||||
when(bookRepository.findAll()).thenReturn(existingBooks());
|
||||
BookService bookService = new BookServiceImpl(bookRepository);
|
||||
|
||||
Collection<Book> storedBooks = bookService.getBooks();
|
||||
assertEquals(3, storedBooks.size());
|
||||
assertThat(storedBooks, hasItem(hasProperty("isbn", equalTo("isbn1"))));
|
||||
assertThat(storedBooks, hasItem(hasProperty("isbn", equalTo("isbn2"))));
|
||||
assertThat(storedBooks, hasItem(hasProperty("isbn", equalTo("isbn3"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAddBook_thenAddSuccessful() {
|
||||
when(bookRepository.findById(anyString())).thenReturn(Optional.empty());
|
||||
when(bookRepository.add(any(BookData.class))).thenAnswer(AdditionalAnswers.returnsFirstArg());
|
||||
BookService bookService = new BookServiceImpl(bookRepository);
|
||||
Book book = bookService.addBook(new Book("isbn1", "name1", "author1"));
|
||||
|
||||
assertEquals("isbn1", book.getIsbn());
|
||||
assertEquals("name1", book.getName());
|
||||
assertEquals("author1", book.getAuthor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBookAlreadyExist_whenAddBook_thenDuplicateBookException() {
|
||||
BookData existingBook = new BookData("isbn1", "name1", "author1");
|
||||
when(bookRepository.findById("isbn1")).thenReturn(Optional.of(existingBook));
|
||||
BookService bookService = new BookServiceImpl(bookRepository);
|
||||
Book bookToBeAdded = new Book("isbn1", "name1", "author1");
|
||||
|
||||
assertThrows(DuplicateBookException.class, () -> bookService.addBook(bookToBeAdded));
|
||||
}
|
||||
|
||||
private static Collection<BookData> existingBooks() {
|
||||
List<BookData> books = new ArrayList<>();
|
||||
books.add(new BookData("isbn1", "name1", "author1"));
|
||||
books.add(new BookData("isbn2", "name2", "author2"));
|
||||
books.add(new BookData("isbn3", "name3", "author3"));
|
||||
return books;
|
||||
}
|
||||
}
|
|
@ -136,7 +136,6 @@
|
|||
<log4j2.version>2.8.2</log4j2.version>
|
||||
<powermock.version>2.0.0</powermock.version>
|
||||
<maven-surefire-plugin.version>2.22.0</maven-surefire-plugin.version>
|
||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||
<spring.version>5.0.1.RELEASE</spring.version>
|
||||
<surefire.report.plugin>3.0.0-M3</surefire.report.plugin>
|
||||
</properties>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue