Merge branch 'eugenp:master' into master

This commit is contained in:
rvsathe 2021-09-03 08:30:15 +05:30 committed by GitHub
commit 935f5d24e7
104 changed files with 5140 additions and 13214 deletions

View File

@ -12,6 +12,7 @@ This module contains articles about Apache Kafka.
- [Kafka Connect Example with MQTT and MongoDB](https://www.baeldung.com/kafka-connect-mqtt-mongodb) - [Kafka Connect Example with MQTT and MongoDB](https://www.baeldung.com/kafka-connect-mqtt-mongodb)
- [Building a Data Pipeline with Flink and Kafka](https://www.baeldung.com/kafka-flink-data-pipeline) - [Building a Data Pipeline with Flink and Kafka](https://www.baeldung.com/kafka-flink-data-pipeline)
- [Exactly Once Processing in Kafka with Java](https://www.baeldung.com/kafka-exactly-once) - [Exactly Once Processing in Kafka with Java](https://www.baeldung.com/kafka-exactly-once)
- [Custom Serializers in Apache Kafka](https://www.baeldung.com/kafka-custom-serializer)
##### Building the project ##### Building the project

File diff suppressed because it is too large Load Diff

View File

@ -2,3 +2,4 @@
- [String API Updates in Java 12](https://www.baeldung.com/java12-string-api) - [String API Updates in Java 12](https://www.baeldung.com/java12-string-api)
- [New Features in Java 12](https://www.baeldung.com/java-12-new-features) - [New Features in Java 12](https://www.baeldung.com/java-12-new-features)
- [Compare the Content of Two Files in Java](https://www.baeldung.com/java-compare-files)

View File

@ -0,0 +1,49 @@
package com.baeldung.java_16_features.mapmulti;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
public class Album {
private String albumName;
private int albumCost;
private List<Artist> artists;
Album(String name, int albumCost, List<Artist> artists) {
this.albumName = name;
this.artists = artists;
this.albumCost = albumCost;
}
public void artistAlbumPairsToMajorLabels(Consumer<Pair<String, String>> consumer) {
for (Artist artist : artists) {
if (artist.isAssociatedMajorLabels()) {
String concatLabels = artist.getMajorLabels()
.stream()
.collect(Collectors.joining(","));
consumer.accept(new ImmutablePair<>(artist.getName() + ":" + albumName, concatLabels));
}
}
}
public String getAlbumName() {
return albumName;
}
public int getAlbumCost() {
return albumCost;
}
List<Artist> getArtists() {
return artists;
}
public String toString() {
return albumName;
}
}

View File

@ -0,0 +1,50 @@
package com.baeldung.java_16_features.mapmulti;
import java.util.List;
import java.util.Objects;
public class Artist {
private final String name;
private boolean associatedMajorLabels;
private List<String> majorLabels;
Artist(String name, boolean associatedMajorLabels, List<String> majorLabels) {
this.name = name;
this.associatedMajorLabels = associatedMajorLabels;
this.majorLabels = majorLabels;
}
public String getName() {
return name;
}
public boolean isAssociatedMajorLabels() {
return associatedMajorLabels;
}
public List<String> getMajorLabels() {
return majorLabels;
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Artist other = (Artist) obj;
return Objects.equals(name, other.name);
}
public String toString() {
return name;
}
}

View File

@ -0,0 +1,134 @@
package com.baeldung.java_16_features.mapmulti;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.offset;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.Test;
public class JavaStreamMapMultiUnitTest {
private static final List<Album> albums = Arrays.asList(new Album("album1", 10, Arrays.asList(new Artist("bob", true, Arrays.asList("label1", "label3")), new Artist("tom", true, Arrays.asList("label2", "label3")))),
new Album("album2", 20, Arrays.asList(new Artist("bill", true, Arrays.asList("label2", "label3")), new Artist("tom", true, Arrays.asList("label2", "label4")))));
@Test
public void givenAListOfintegers_whenMapMulti_thenGetListOfOfEvenDoublesPlusPercentage() {
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
double percentage = .01;
List<Double> evenDoubles = integers.stream()
.<Double> mapMulti((integer, consumer) -> {
if (integer % 2 == 0) {
consumer.accept((double) integer * (1 + percentage));
}
})
.collect(toList());
assertThat(evenDoubles).containsAll(Arrays.asList(2.02D, 4.04D));
}
@Test
public void givenAListOfintegers_whenFilterMap_thenGetListOfOfEvenDoublesPlusPercentage() {
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
double percentage = .01;
List<Double> evenDoubles = integers.stream()
.filter(integer -> integer % 2 == 0)
.<Double> map(integer -> ((double) integer * (1 + percentage)))
.collect(toList());
assertThat(evenDoubles).containsAll(Arrays.asList(2.02D, 4.04D));
}
@Test
public void givenAListOfintegers_whenMapMultiToDouble_thenGetSumOfEvenNumbersAfterApplyPercentage() {
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
double percentage = .01;
double sum = integers.stream()
.mapMultiToDouble((integer, consumer) -> {
if (integer % 2 == 0) {
consumer.accept(integer * (1 + percentage));
}
})
.sum();
assertThat(sum).isEqualTo(12.12, offset(0.001d));
}
@Test
public void givenAListOfAlbums_whenFlatMap_thenGetListOfArtistAlbumPairs() {
List<Pair<String, String>> artistAlbum = albums.stream()
.flatMap(album -> album.getArtists()
.stream()
.map(artist -> new ImmutablePair<String, String>(artist.getName(), album.getAlbumName())))
.collect(toList());
assertThat(artistAlbum).contains(new ImmutablePair<String, String>("bob", "album1"), new ImmutablePair<String,
String>("tom", "album1"), new ImmutablePair<String, String>("bill", "album2"), new ImmutablePair<String, String>("tom", "album2"));
}
@Test
public void givenAListOfAlbums_whenMapMulti_thenGetListOfPairsOfArtistAlbum() {
List<Pair<String, String>> artistAlbum = albums.stream()
.<Pair<String, String>> mapMulti((album, consumer) -> {
for (Artist artist : album.getArtists()) {
consumer.accept(new ImmutablePair<String, String>(artist.getName(), album.getAlbumName()));
}
})
.collect(toList());
assertThat(artistAlbum).contains(new ImmutablePair<String, String>("bob", "album1"), new ImmutablePair<String, String>("tom", "album1"),
new ImmutablePair<String, String>("bill", "album2"), new ImmutablePair<String, String>("tom", "album2"));
}
@Test
public void givenAListOfAlbums_whenFlatMap_thenGetListOfArtistAlbumjPairsBelowGivenCost() {
int upperCost = 9;
List<Pair<String, String>> artistAlbum = albums.stream()
.flatMap(album -> album.getArtists()
.stream()
.filter(artist -> upperCost > album.getAlbumCost())
.map(artist -> new ImmutablePair<String, String>(artist.getName(), album.getAlbumName())))
.collect(toList());
assertTrue(artistAlbum.isEmpty());
}
@Test
public void givenAListOfAlbums_whenMapMulti_thenGetListOfArtistAlbumPairsBelowGivenCost() {
int upperCost = 9;
List<Pair<String, String>> artistAlbum = albums.stream()
.<Pair<String, String>> mapMulti((album, consumer) -> {
if (album.getAlbumCost() < upperCost) {
for (Artist artist : album.getArtists()) {
consumer.accept(new ImmutablePair<String, String>(artist.getName(), album.getAlbumName()));
}
}
})
.collect(toList());
assertTrue(artistAlbum.isEmpty());
}
@Test
public void givenAListOfAlbums_whenMapMulti_thenGetPairsOfArtistMajorLabelsUsingMethodReference() {
List<Pair<String, String>> artistLabels = albums.stream()
.mapMulti(Album::artistAlbumPairsToMajorLabels)
.collect(toList());
assertThat(artistLabels).contains(new ImmutablePair<String, String>("bob:album1", "label1,label3"), new ImmutablePair<String, String>("tom:album1", "label2,label3"),
new ImmutablePair<String, String>("bill:album2", "label2,label3"), new ImmutablePair<String, String>("tom:album2", "label2,label4"));
}
}

View File

@ -11,3 +11,4 @@ This module contains articles about parsing and formatting Java date and time ob
- [Display All Time Zones With GMT And UTC in Java](http://www.baeldung.com/java-time-zones) - [Display All Time Zones With GMT And UTC in Java](http://www.baeldung.com/java-time-zones)
- [Convert between String and Timestamp](https://www.baeldung.com/java-string-to-timestamp) - [Convert between String and Timestamp](https://www.baeldung.com/java-string-to-timestamp)
- [Convert String to Date in Java](http://www.baeldung.com/java-string-to-date) - [Convert String to Date in Java](http://www.baeldung.com/java-string-to-date)
- [Format a Milliseconds Duration to HH:MM:SS](https://www.baeldung.com/java-ms-to-hhmmss)

View File

@ -75,7 +75,7 @@
<properties> <properties>
<commons-validator.version>1.6</commons-validator.version> <commons-validator.version>1.6</commons-validator.version>
<joda-time.version>2.10</joda-time.version> <joda-time.version>2.10.10</joda-time.version>
<!-- testing --> <!-- testing -->
<assertj.version>3.6.1</assertj.version> <assertj.version>3.6.1</assertj.version>
<maven.compiler.source>1.9</maven.compiler.source> <maven.compiler.source>1.9</maven.compiler.source>

View File

@ -0,0 +1,54 @@
package com.baeldung.formatduration;
import org.apache.commons.lang3.time.DurationFormatUtils;
import org.joda.time.Period;
import org.junit.Test;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
public class FormatDurationUnitTest {
@Test
public void givenInterval_WhenFormatInterval_formatDuration() {
long HH = TimeUnit.MILLISECONDS.toHours(38114000);
long MM = TimeUnit.MILLISECONDS.toMinutes(38114000) % 60;
long SS = TimeUnit.MILLISECONDS.toSeconds(38114000) % 60;
String timeInHHMMSS = String.format("%02d:%02d:%02d", HH, MM, SS);
assertThat(timeInHHMMSS).isEqualTo("10:35:14");
}
@Test
public void givenInterval_WhenFormatUsingDuration_formatDuration() {
Duration duration = Duration.ofMillis(38114000);
long seconds = duration.getSeconds();
long HH = seconds / 3600;
long MM = (seconds % 3600) / 60;
long SS = seconds % 60;
String timeInHHMMSS = String.format("%02d:%02d:%02d", HH, MM, SS);
assertThat(timeInHHMMSS).isEqualTo("10:35:14");
}
@Test
public void givenInterval_WhenFormatDurationUsingApacheCommons_formatDuration() {
assertThat(DurationFormatUtils.formatDuration(38114000, "HH:mm:ss"))
.isEqualTo("10:35:14");
}
@Test
public void givenInterval_WhenFormatDurationUsingJodaTime_formatDuration() {
org.joda.time.Duration duration = new org.joda.time.Duration(38114000);
Period period = duration.toPeriod();
long HH = period.getHours();
long MM = period.getMinutes();
long SS = period.getSeconds();
String timeInHHMMSS = String.format("%02d:%02d:%02d", HH, MM, SS);
assertThat(timeInHHMMSS).isEqualTo("10:35:14");
}
}

View File

@ -4,4 +4,5 @@ This module contains articles about JavaFX.
### Relevant Articles: ### Relevant Articles:
- [Introduction to JavaFX](https://www.baeldung.com/javafx) - [Introduction to JavaFX](https://www.baeldung.com/javafx)
- [Display Custom Items in JavaFX ListView](https://www.baeldung.com/javafx-listview-display-custom-items)

View File

@ -17,7 +17,6 @@
</prerequisites> </prerequisites>
<properties> <properties>
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
<argLine>-Djava.security.egd=file:/dev/./urandom -Xmx256m</argLine> <argLine>-Djava.security.egd=file:/dev/./urandom -Xmx256m</argLine>
<assertj.version>3.6.2</assertj.version> <assertj.version>3.6.2</assertj.version>
<awaitility.version>2.0.0</awaitility.version> <awaitility.version>2.0.0</awaitility.version>
@ -31,6 +30,7 @@
<jcache.version>1.0.0</jcache.version> <jcache.version>1.0.0</jcache.version>
<jhipster.server.version>1.1.0</jhipster.server.version> <jhipster.server.version>1.1.0</jhipster.server.version>
<jjwt.version>0.7.0</jjwt.version> <jjwt.version>0.7.0</jjwt.version>
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
<liquibase-hibernate5.version>3.6</liquibase-hibernate5.version> <liquibase-hibernate5.version>3.6</liquibase-hibernate5.version>
<liquibase-slf4j.version>2.0.0</liquibase-slf4j.version> <liquibase-slf4j.version>2.0.0</liquibase-slf4j.version>
<liquibase.version>3.6.2</liquibase.version> <liquibase.version>3.6.2</liquibase.version>
@ -349,7 +349,6 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -365,11 +364,6 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Cloud --> <!-- Spring Cloud -->
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
@ -580,14 +574,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Force alphabetical order to have a reproducible build -->
<runOrder>alphabetical</runOrder>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>

View File

@ -21,6 +21,8 @@ eureka:
instanceId: carapp:${spring.application.instance_id:${random.value}} instanceId: carapp:${spring.application.instance_id:${random.value}}
spring: spring:
main:
banner-mode: "off"
application: application:
name: carapp name: carapp
jackson: jackson:
@ -37,7 +39,7 @@ spring:
database-platform: io.github.jhipster.domain.util.FixedH2Dialect database-platform: io.github.jhipster.domain.util.FixedH2Dialect
database: H2 database: H2
open-in-view: false open-in-view: false
show-sql: true show-sql: false
hibernate: hibernate:
ddl-auto: none ddl-auto: none
naming: naming:

View File

@ -3,7 +3,7 @@
<configuration scan="true"> <configuration scan="true">
<include resource="org/springframework/boot/logging/logback/base.xml"/> <include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="com.car.app" level="DEBUG"/> <logger name="com.car.app" level="INFO"/>
<logger name="org.hibernate" level="WARN"/> <logger name="org.hibernate" level="WARN"/>
<logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/> <logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/>
<logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/> <logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/>

View File

@ -29,6 +29,7 @@
<jcache.version>1.0.0</jcache.version> <jcache.version>1.0.0</jcache.version>
<jhipster.server.version>1.1.0</jhipster.server.version> <jhipster.server.version>1.1.0</jhipster.server.version>
<jjwt.version>0.7.0</jjwt.version> <jjwt.version>0.7.0</jjwt.version>
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
<liquibase-hibernate5.version>3.6</liquibase-hibernate5.version> <liquibase-hibernate5.version>3.6</liquibase-hibernate5.version>
<liquibase-slf4j.version>2.0.0</liquibase-slf4j.version> <liquibase-slf4j.version>2.0.0</liquibase-slf4j.version>
<liquibase.version>3.6.2</liquibase.version> <liquibase.version>3.6.2</liquibase.version>
@ -90,7 +91,6 @@
<undertow.version>1.4.10.Final</undertow.version> <undertow.version>1.4.10.Final</undertow.version>
<validation-api.version>1.1.0.Final</validation-api.version> <validation-api.version>1.1.0.Final</validation-api.version>
<yarn.version>v0.21.3</yarn.version> <yarn.version>v0.21.3</yarn.version>
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
@ -345,6 +345,10 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-security</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId> <artifactId>spring-boot-starter-thymeleaf</artifactId>
@ -359,11 +363,6 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Cloud --> <!-- Spring Cloud -->
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
@ -574,14 +573,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Force alphabetical order to have a reproducible build -->
<runOrder>alphabetical</runOrder>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>

View File

@ -21,6 +21,8 @@ eureka:
instanceId: dealerapp:${spring.application.instance_id:${random.value}} instanceId: dealerapp:${spring.application.instance_id:${random.value}}
spring: spring:
main:
banner-mode: "off"
application: application:
name: dealerapp name: dealerapp
jackson: jackson:
@ -37,7 +39,7 @@ spring:
database-platform: io.github.jhipster.domain.util.FixedH2Dialect database-platform: io.github.jhipster.domain.util.FixedH2Dialect
database: H2 database: H2
open-in-view: false open-in-view: false
show-sql: true show-sql: false
hibernate: hibernate:
ddl-auto: none ddl-auto: none
naming: naming:

View File

@ -3,7 +3,7 @@
<configuration scan="true"> <configuration scan="true">
<include resource="org/springframework/boot/logging/logback/base.xml"/> <include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="com.dealer.app" level="DEBUG"/> <logger name="com.dealer.app" level="INFO"/>
<logger name="org.hibernate" level="WARN"/> <logger name="org.hibernate" level="WARN"/>
<logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/> <logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/>
<logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/> <logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/>

View File

@ -32,6 +32,7 @@
<jcache.version>1.0.0</jcache.version> <jcache.version>1.0.0</jcache.version>
<jhipster.server.version>1.1.0</jhipster.server.version> <jhipster.server.version>1.1.0</jhipster.server.version>
<jjwt.version>0.7.0</jjwt.version> <jjwt.version>0.7.0</jjwt.version>
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
<liquibase-hibernate5.version>3.6</liquibase-hibernate5.version> <liquibase-hibernate5.version>3.6</liquibase-hibernate5.version>
<liquibase-slf4j.version>2.0.0</liquibase-slf4j.version> <liquibase-slf4j.version>2.0.0</liquibase-slf4j.version>
<liquibase.version>3.6.2</liquibase.version> <liquibase.version>3.6.2</liquibase.version>
@ -94,7 +95,6 @@
<undertow.version>1.4.10.Final</undertow.version> <undertow.version>1.4.10.Final</undertow.version>
<validation-api.version>1.1.0.Final</validation-api.version> <validation-api.version>1.1.0.Final</validation-api.version>
<yarn.version>v0.21.3</yarn.version> <yarn.version>v0.21.3</yarn.version>
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
@ -383,6 +383,10 @@
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId> <artifactId>spring-boot-starter-thymeleaf</artifactId>
@ -397,11 +401,6 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId> <artifactId>spring-cloud-starter</artifactId>
@ -632,14 +631,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Force alphabetical order to have a reproducible build -->
<runOrder>alphabetical</runOrder>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>

View File

@ -49,7 +49,7 @@ public class LogsResourceIntegrationTest {
public void changeLogs()throws Exception { public void changeLogs()throws Exception {
LoggerVM logger = new LoggerVM(); LoggerVM logger = new LoggerVM();
logger.setLevel("INFO"); logger.setLevel("INFO");
logger.setName("ROOT"); logger.setName("some.test.logger");
restLogsMockMvc.perform(put("/management/logs") restLogsMockMvc.perform(put("/management/logs")
.contentType(TestUtil.APPLICATION_JSON_UTF8) .contentType(TestUtil.APPLICATION_JSON_UTF8)

View File

@ -21,6 +21,8 @@ eureka:
instanceId: gateway:${spring.application.instance_id:${random.value}} instanceId: gateway:${spring.application.instance_id:${random.value}}
spring: spring:
main:
banner-mode: "off"
application: application:
name: gateway name: gateway
autoconfigure: autoconfigure:
@ -39,7 +41,7 @@ spring:
database-platform: io.github.jhipster.domain.util.FixedH2Dialect database-platform: io.github.jhipster.domain.util.FixedH2Dialect
database: H2 database: H2
open-in-view: false open-in-view: false
show-sql: true show-sql: false
hibernate: hibernate:
ddl-auto: none ddl-auto: none
naming: naming:

View File

@ -3,7 +3,7 @@
<configuration scan="true"> <configuration scan="true">
<include resource="org/springframework/boot/logging/logback/base.xml"/> <include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="com.gateway" level="DEBUG"/> <logger name="com.gateway" level="INFO"/>
<logger name="org.hibernate" level="WARN"/> <logger name="org.hibernate" level="WARN"/>
<logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/> <logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/>
<logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/> <logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/>

View File

@ -277,8 +277,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> </dependency>
<!-- security --> <!-- security -->
<dependency> <dependency>

View File

@ -49,7 +49,7 @@ public class LogsResourceIntegrationTest {
public void changeLogs()throws Exception { public void changeLogs()throws Exception {
LoggerVM logger = new LoggerVM(); LoggerVM logger = new LoggerVM();
logger.setLevel("INFO"); logger.setLevel("INFO");
logger.setName("ROOT"); logger.setName("some.test.logger");
restLogsMockMvc.perform(put("/management/logs") restLogsMockMvc.perform(put("/management/logs")
.contentType(TestUtil.APPLICATION_JSON_UTF8) .contentType(TestUtil.APPLICATION_JSON_UTF8)

View File

@ -15,6 +15,8 @@
spring: spring:
main:
banner-mode: "off"
application: application:
name: baeldung name: baeldung
jackson: jackson:
@ -31,7 +33,7 @@ spring:
database-platform: io.github.jhipster.domain.util.FixedH2Dialect database-platform: io.github.jhipster.domain.util.FixedH2Dialect
database: H2 database: H2
open-in-view: false open-in-view: false
show-sql: true show-sql: false
hibernate: hibernate:
ddl-auto: none ddl-auto: none
naming: naming:

View File

@ -3,7 +3,7 @@
<configuration scan="true"> <configuration scan="true">
<include resource="org/springframework/boot/logging/logback/base.xml"/> <include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="com.baeldung" level="DEBUG"/> <logger name="com.baeldung" level="INFO"/>
<logger name="org.hibernate" level="WARN"/> <logger name="org.hibernate" level="WARN"/>
<logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/> <logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/>
<logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/> <logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/>

View File

@ -1,6 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>jhipster-uaa</artifactId>
<groupId>com.baeldung.jhipster</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>com.baeldung.jhipster.gateway</groupId> <groupId>com.baeldung.jhipster.gateway</groupId>
<artifactId>gateway</artifactId> <artifactId>gateway</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
@ -415,15 +422,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<!-- Force alphabetical order to have a reproducible build -->
<runOrder>alphabetical</runOrder>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>

View File

@ -40,7 +40,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
* *
* @see WebConfigurer * @see WebConfigurer
*/ */
public class WebConfigurerTest { public class WebConfigurerUnitTest {
private WebConfigurer webConfigurer; private WebConfigurer webConfigurer;

View File

@ -18,7 +18,7 @@ import static springfox.documentation.swagger2.web.Swagger2Controller.DEFAULT_UR
/** /**
* Tests SwaggerBasePathRewritingFilter class. * Tests SwaggerBasePathRewritingFilter class.
*/ */
public class SwaggerBasePathRewritingFilterTest { public class SwaggerBasePathRewritingFilterUnitTest {
private SwaggerBasePathRewritingFilter filter = new SwaggerBasePathRewritingFilter(); private SwaggerBasePathRewritingFilter filter = new SwaggerBasePathRewritingFilter();

View File

@ -16,7 +16,7 @@ import java.util.List;
* *
* @see CookieCollection * @see CookieCollection
*/ */
public class CookieCollectionTest { public class CookieCollectionUnitTest {
public static final String COOKIE_NAME = "chocolate"; public static final String COOKIE_NAME = "chocolate";
public static final String COOKIE_VALUE = "yummy"; public static final String COOKIE_VALUE = "yummy";
public static final String BROWNIE_NAME = "brownie"; public static final String BROWNIE_NAME = "brownie";

View File

@ -12,7 +12,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken;
* Test whether the CookieTokenExtractor can properly extract access tokens from * Test whether the CookieTokenExtractor can properly extract access tokens from
* Cookies and Headers. * Cookies and Headers.
*/ */
public class CookieTokenExtractorTest { public class CookieTokenExtractorUnitTest {
private CookieTokenExtractor cookieTokenExtractor; private CookieTokenExtractor cookieTokenExtractor;
@Before @Before
@ -22,24 +22,24 @@ public class CookieTokenExtractorTest {
@Test @Test
public void testExtractTokenCookie() { public void testExtractTokenCookie() {
MockHttpServletRequest request = OAuth2AuthenticationServiceTest.createMockHttpServletRequest(); MockHttpServletRequest request = OAuth2AuthenticationServiceUnitTest.createMockHttpServletRequest();
Authentication authentication = cookieTokenExtractor.extract(request); Authentication authentication = cookieTokenExtractor.extract(request);
Assert.assertEquals(OAuth2AuthenticationServiceTest.ACCESS_TOKEN_VALUE, authentication.getPrincipal().toString()); Assert.assertEquals(OAuth2AuthenticationServiceUnitTest.ACCESS_TOKEN_VALUE, authentication.getPrincipal().toString());
} }
@Test @Test
public void testExtractTokenHeader() { public void testExtractTokenHeader() {
MockHttpServletRequest request = new MockHttpServletRequest(HttpMethod.GET.name(), "http://www.test.com"); MockHttpServletRequest request = new MockHttpServletRequest(HttpMethod.GET.name(), "http://www.test.com");
request.addHeader("Authorization", OAuth2AccessToken.BEARER_TYPE + " " + OAuth2AuthenticationServiceTest.ACCESS_TOKEN_VALUE); request.addHeader("Authorization", OAuth2AccessToken.BEARER_TYPE + " " + OAuth2AuthenticationServiceUnitTest.ACCESS_TOKEN_VALUE);
Authentication authentication = cookieTokenExtractor.extract(request); Authentication authentication = cookieTokenExtractor.extract(request);
Assert.assertEquals(OAuth2AuthenticationServiceTest.ACCESS_TOKEN_VALUE, authentication.getPrincipal().toString()); Assert.assertEquals(OAuth2AuthenticationServiceUnitTest.ACCESS_TOKEN_VALUE, authentication.getPrincipal().toString());
} }
@Test @Test
public void testExtractTokenParam() { public void testExtractTokenParam() {
MockHttpServletRequest request = new MockHttpServletRequest(HttpMethod.GET.name(), "http://www.test.com"); MockHttpServletRequest request = new MockHttpServletRequest(HttpMethod.GET.name(), "http://www.test.com");
request.addParameter(OAuth2AccessToken.ACCESS_TOKEN, OAuth2AuthenticationServiceTest.ACCESS_TOKEN_VALUE); request.addParameter(OAuth2AccessToken.ACCESS_TOKEN, OAuth2AuthenticationServiceUnitTest.ACCESS_TOKEN_VALUE);
Authentication authentication = cookieTokenExtractor.extract(request); Authentication authentication = cookieTokenExtractor.extract(request);
Assert.assertEquals(OAuth2AuthenticationServiceTest.ACCESS_TOKEN_VALUE, authentication.getPrincipal().toString()); Assert.assertEquals(OAuth2AuthenticationServiceUnitTest.ACCESS_TOKEN_VALUE, authentication.getPrincipal().toString());
} }
} }

View File

@ -39,7 +39,7 @@ import static org.mockito.Mockito.when;
* @see OAuth2AuthenticationService * @see OAuth2AuthenticationService
*/ */
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class OAuth2AuthenticationServiceTest { public class OAuth2AuthenticationServiceUnitTest {
public static final String CLIENT_AUTHORIZATION = "Basic d2ViX2FwcDpjaGFuZ2VpdA=="; public static final String CLIENT_AUTHORIZATION = "Basic d2ViX2FwcDpjaGFuZ2VpdA==";
public static final String ACCESS_TOKEN_VALUE = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQyNzI4NDQsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiNzc1ZTJkYWUtYWYzZi00YTdhLWExOTktNzNiZTU1MmIxZDVkIiwiY2xpZW50X2lkIjoid2ViX2FwcCIsInNjb3BlIjpbIm9wZW5pZCJdfQ.gEK0YcX2IpkpxnkxXXHQ4I0xzTjcy7edqb89ukYE0LPe7xUcZVwkkCJF_nBxsGJh2jtA6NzNLfY5zuL6nP7uoAq3fmvsyrcyR2qPk8JuuNzGtSkICx3kPDRjAT4ST8SZdeh7XCbPVbySJ7ZmPlRWHyedzLA1wXN0NUf8yZYS4ELdUwVBYIXSjkNoKqfWm88cwuNr0g0teypjPtjDqCnXFt1pibwdfIXn479Y1neNAdvSpHcI4Ost-c7APCNxW2gqX-0BItZQearxRgKDdBQ7CGPAIky7dA0gPuKUpp_VCoqowKCXqkE9yKtRQGIISewtj2UkDRZePmzmYrUBXRzfYw"; public static final String ACCESS_TOKEN_VALUE = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQyNzI4NDQsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiNzc1ZTJkYWUtYWYzZi00YTdhLWExOTktNzNiZTU1MmIxZDVkIiwiY2xpZW50X2lkIjoid2ViX2FwcCIsInNjb3BlIjpbIm9wZW5pZCJdfQ.gEK0YcX2IpkpxnkxXXHQ4I0xzTjcy7edqb89ukYE0LPe7xUcZVwkkCJF_nBxsGJh2jtA6NzNLfY5zuL6nP7uoAq3fmvsyrcyR2qPk8JuuNzGtSkICx3kPDRjAT4ST8SZdeh7XCbPVbySJ7ZmPlRWHyedzLA1wXN0NUf8yZYS4ELdUwVBYIXSjkNoKqfWm88cwuNr0g0teypjPtjDqCnXFt1pibwdfIXn479Y1neNAdvSpHcI4Ost-c7APCNxW2gqX-0BItZQearxRgKDdBQ7CGPAIky7dA0gPuKUpp_VCoqowKCXqkE9yKtRQGIISewtj2UkDRZePmzmYrUBXRzfYw";
public static final String REFRESH_TOKEN_VALUE = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJ1c2VyIiwic2NvcGUiOlsib3BlbmlkIl0sImF0aSI6Ijc3NWUyZGFlLWFmM2YtNGE3YS1hMTk5LTczYmU1NTJiMWQ1ZCIsImV4cCI6MTQ5Njg2NDc0MywiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6IjhmYjI2YTllLTdjYzQtNDFlMi1hNzBjLTk4MDc0N2U2YWFiOSIsImNsaWVudF9pZCI6IndlYl9hcHAifQ.q1-Df9_AFO6TJNiLKV2YwTjRbnd7qcXv52skXYnog5siHYRoR6cPtm6TNQ04iDAoIHljTSTNnD6DS3bHk41mV55gsSVxGReL8VCb_R8ZmhVL4-5yr90sfms0wFp6lgD2bPmZ-TXiS2Oe9wcbNWagy5RsEplZ-sbXu3tjmDao4FN35ojPsXmUs84XnNQH3Y_-PY9GjZG0JEfLQIvE0J5BkXS18Z015GKyA6GBIoLhAGBQQYyG9m10ld_a9fD5SmCyCF72Jad_pfP1u8Z_WyvO-wrlBvm2x-zBthreVrXU5mOb9795wJEP-xaw3dXYGjht_grcW4vKUFtj61JgZk98CQ"; public static final String REFRESH_TOKEN_VALUE = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJ1c2VyIiwic2NvcGUiOlsib3BlbmlkIl0sImF0aSI6Ijc3NWUyZGFlLWFmM2YtNGE3YS1hMTk5LTczYmU1NTJiMWQ1ZCIsImV4cCI6MTQ5Njg2NDc0MywiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6IjhmYjI2YTllLTdjYzQtNDFlMi1hNzBjLTk4MDc0N2U2YWFiOSIsImNsaWVudF9pZCI6IndlYl9hcHAifQ.q1-Df9_AFO6TJNiLKV2YwTjRbnd7qcXv52skXYnog5siHYRoR6cPtm6TNQ04iDAoIHljTSTNnD6DS3bHk41mV55gsSVxGReL8VCb_R8ZmhVL4-5yr90sfms0wFp6lgD2bPmZ-TXiS2Oe9wcbNWagy5RsEplZ-sbXu3tjmDao4FN35ojPsXmUs84XnNQH3Y_-PY9GjZG0JEfLQIvE0J5BkXS18Z015GKyA6GBIoLhAGBQQYyG9m10ld_a9fD5SmCyCF72Jad_pfP1u8Z_WyvO-wrlBvm2x-zBthreVrXU5mOb9795wJEP-xaw3dXYGjht_grcW4vKUFtj61JgZk98CQ";

View File

@ -12,7 +12,7 @@ import org.springframework.test.util.ReflectionTestUtils;
* *
* @see OAuth2CookieHelper * @see OAuth2CookieHelper
*/ */
public class OAuth2CookieHelperTest { public class OAuth2CookieHelperUnitTest {
public static final String GET_COOKIE_DOMAIN_METHOD = "getCookieDomain"; public static final String GET_COOKIE_DOMAIN_METHOD = "getCookieDomain";
private OAuth2Properties oAuth2Properties; private OAuth2Properties oAuth2Properties;
private OAuth2CookieHelper cookieHelper; private OAuth2CookieHelper cookieHelper;

View File

@ -51,7 +51,7 @@ public class LogsResourceIntTest {
public void changeLogs() throws Exception { public void changeLogs() throws Exception {
LoggerVM logger = new LoggerVM(); LoggerVM logger = new LoggerVM();
logger.setLevel("INFO"); logger.setLevel("INFO");
logger.setName("ROOT"); logger.setName("some.test.logger");
restLogsMockMvc.perform(put("/management/logs") restLogsMockMvc.perform(put("/management/logs")
.contentType(TestUtil.APPLICATION_JSON_UTF8) .contentType(TestUtil.APPLICATION_JSON_UTF8)

View File

@ -21,6 +21,8 @@ eureka:
instanceId: gateway:${spring.application.instance-id:${random.value}} instanceId: gateway:${spring.application.instance-id:${random.value}}
spring: spring:
main:
banner-mode: "off"
application: application:
name: gateway name: gateway
cache: cache:

View File

@ -1,6 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>jhipster-uaa</artifactId>
<groupId>com.baeldung.jhipster</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>com.baeldung.jhipster.quotes</groupId> <groupId>com.baeldung.jhipster.quotes</groupId>
<artifactId>quotes</artifactId> <artifactId>quotes</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
@ -399,15 +406,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<!-- Force alphabetical order to have a reproducible build -->
<runOrder>alphabetical</runOrder>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>

View File

@ -38,7 +38,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
* *
* @see WebConfigurer * @see WebConfigurer
*/ */
public class WebConfigurerTest { public class WebConfigurerUnitTest {
private WebConfigurer webConfigurer; private WebConfigurer webConfigurer;

View File

@ -51,7 +51,7 @@ public class LogsResourceIntTest {
public void changeLogs() throws Exception { public void changeLogs() throws Exception {
LoggerVM logger = new LoggerVM(); LoggerVM logger = new LoggerVM();
logger.setLevel("INFO"); logger.setLevel("INFO");
logger.setName("ROOT"); logger.setName("some.test.logger");
restLogsMockMvc.perform(put("/management/logs") restLogsMockMvc.perform(put("/management/logs")
.contentType(TestUtil.APPLICATION_JSON_UTF8) .contentType(TestUtil.APPLICATION_JSON_UTF8)

View File

@ -21,6 +21,8 @@ eureka:
instanceId: quotes:${spring.application.instance-id:${random.value}} instanceId: quotes:${spring.application.instance-id:${random.value}}
spring: spring:
main:
banner-mode: "off"
application: application:
name: quotes name: quotes
cache: cache:

View File

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>jhipster-uaa</artifactId>
<groupId>com.baeldung.jhipster</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>com.baeldung.jhipster.uaa</groupId> <groupId>com.baeldung.jhipster.uaa</groupId>
<artifactId>uaa</artifactId> <artifactId>uaa</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
@ -399,15 +405,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<!-- Force alphabetical order to have a reproducible build -->
<runOrder>alphabetical</runOrder>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>

View File

@ -38,7 +38,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
* *
* @see WebConfigurer * @see WebConfigurer
*/ */
public class WebConfigurerTest { public class WebConfigurerUnitTest {
private WebConfigurer webConfigurer; private WebConfigurer webConfigurer;

View File

@ -51,7 +51,7 @@ public class LogsResourceIntTest {
public void changeLogs() throws Exception { public void changeLogs() throws Exception {
LoggerVM logger = new LoggerVM(); LoggerVM logger = new LoggerVM();
logger.setLevel("INFO"); logger.setLevel("INFO");
logger.setName("ROOT"); logger.setName("some.test.logger");
restLogsMockMvc.perform(put("/management/logs") restLogsMockMvc.perform(put("/management/logs")
.contentType(TestUtil.APPLICATION_JSON_UTF8) .contentType(TestUtil.APPLICATION_JSON_UTF8)

View File

@ -21,6 +21,8 @@ eureka:
instanceId: uaa:${spring.application.instance-id:${random.value}} instanceId: uaa:${spring.application.instance-id:${random.value}}
spring: spring:
main:
banner-mode: "off"
application: application:
name: uaa name: uaa
cache: cache:

View File

@ -17,11 +17,39 @@
<relativePath>../parent-boot-1</relativePath> <relativePath>../parent-boot-1</relativePath>
</parent> </parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
<exclusion>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</exclusion>
</exclusions>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-java8</artifactId> <artifactId>hibernate-java8</artifactId>
</dependency> </dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>${byte-buddy.version}</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<modules> <modules>

3
ksqldb/README.md Normal file
View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [Introduction to ksqlDB](https://www.baeldung.com/ksqldb)

View File

@ -78,6 +78,29 @@
<artifactId>sshd-core</artifactId> <artifactId>sshd-core</artifactId>
<version>${apache-mina.version}</version> <version>${apache-mina.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.xacml4j</groupId>
<artifactId>xacml-core</artifactId>
<version>${xacml4j.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.xacml4j</groupId>
<artifactId>xacml-test</artifactId>
<version>${xacml4j.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> </dependencies>
<properties> <properties>
@ -90,6 +113,7 @@
<jsch.version>0.1.55</jsch.version> <jsch.version>0.1.55</jsch.version>
<apache-mina.version>2.5.1</apache-mina.version> <apache-mina.version>2.5.1</apache-mina.version>
<spring-security-oauth2.version>2.4.0.RELEASE</spring-security-oauth2.version> <spring-security-oauth2.version>2.4.0.RELEASE</spring-security-oauth2.version>
<xacml4j.version>1.4.0</xacml4j.version>
</properties> </properties>
</project> </project>

View File

@ -2,9 +2,11 @@ package com.baeldung.scribejava;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication @SpringBootApplication
@ServletComponentScan
public class ScribejavaApplication { public class ScribejavaApplication {
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -0,0 +1,27 @@
package com.baeldung.scribejava.controller;
import java.io.IOException;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.servlet.ServletException;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(name="rbac", urlPatterns = {"/protected"})
@DeclareRoles("USER")
@ServletSecurity(
@HttpConstraint(rolesAllowed = "USER")
)
public class RBACController extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("Hello, USER");
}
}

View File

@ -0,0 +1,233 @@
package com.baeldung.xacml4j;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.xacml4j.v20.Xacml20TestUtility;
import org.xacml4j.v30.Attribute;
import org.xacml4j.v30.Categories;
import org.xacml4j.v30.Category;
import org.xacml4j.v30.CompositeDecisionRule;
import org.xacml4j.v30.Decision;
import org.xacml4j.v30.Entity;
import org.xacml4j.v30.RequestContext;
import org.xacml4j.v30.ResponseContext;
import org.xacml4j.v30.Result;
import org.xacml4j.v30.XacmlPolicyTestSupport;
import org.xacml4j.v30.pdp.PolicyDecisionPoint;
import org.xacml4j.v30.pdp.PolicyDecisionPointBuilder;
import org.xacml4j.v30.spi.combine.DecisionCombiningAlgorithmProviderBuilder;
import org.xacml4j.v30.spi.function.FunctionProviderBuilder;
import org.xacml4j.v30.spi.pip.PolicyInformationPointBuilder;
import org.xacml4j.v30.spi.repository.InMemoryPolicyRepository;
import org.xacml4j.v30.spi.repository.PolicyRepository;
import org.xacml4j.v30.types.DoubleExp;
import org.xacml4j.v30.types.StringExp;
import org.xacml4j.v30.types.TimeExp;
public class NightlyWithdrawalPolicyUnitTest extends XacmlPolicyTestSupport {
private static final String POLICY_SET = "xacml4j/NightlyWithdrawalsPolicy.xml";
@Test
public void testWhenNightlyWithdrawalOver500_thenFail() throws Exception {
PolicyDecisionPoint pdp = buildPDP(POLICY_SET);
// Action category
Attribute actionAttribute = Attribute.builder("urn:oasis:names:tc:xacml:1.0:action:action-id")
.value(StringExp.of("withdrawal"))
.build();
Entity actionEntity = Entity.builder()
.attribute(actionAttribute)
.build();
Category actionCategory = Category.builder(Categories.ACTION)
.entity(actionEntity)
.build();
// Environment Category
Attribute timeAttribute = Attribute.builder("urn:oasis:names:tc:xacml:1.0:environment:current-time")
.includeInResult(false)
.value(TimeExp.of("21:00:00"))
.build();
Entity timeEntity = Entity.builder()
.attribute(timeAttribute)
.build();
Category environmentCategory = Category.builder(Categories.ENVIRONMENT)
.entity(timeEntity)
.build();
// ATM category
Attribute amountAttribute = Attribute.builder("urn:baeldung:atm:withdrawal:amount")
.value(DoubleExp.of("1200.00"))
.build();
Entity atmEntity = Entity.builder()
.attribute(amountAttribute)
.build();
Category atmCategory = Category.builder(Categories.parse("urn:baeldung:atm:withdrawal"))
.entity(atmEntity)
.build();
RequestContext request = RequestContext.builder()
.attributes(actionCategory, environmentCategory, atmCategory)
.build();
ResponseContext response = pdp.decide(request);
assertNotNull(response);
assertTrue("Shoud have at least one result", response.getResults() != null && !response.getResults()
.isEmpty());
Result result = response.getResults()
.iterator()
.next();
assertTrue("Evaluation should succeed", result.getStatus()
.isSuccess());
assertEquals("Should DENY withdrawal", Decision.DENY, result.getDecision());
}
@Test
public void testWhenNightlyWithdrawalUnder500_thenSuccess() throws Exception {
PolicyDecisionPoint pdp = buildPDP(POLICY_SET);
// Action category
Attribute actionAttribute = Attribute.builder("urn:oasis:names:tc:xacml:1.0:action:action-id")
.includeInResult(false)
.value(StringExp.of("withdrawal"))
.build();
Entity actionEntity = Entity.builder()
.attribute(actionAttribute)
.build();
Category actionCategory = Category.builder(Categories.ACTION)
.entity(actionEntity)
.build();
// Environment Category
Attribute timeAttribute = Attribute.builder("urn:oasis:names:tc:xacml:1.0:environment:current-time")
.includeInResult(false)
.value(TimeExp.of("21:00:00"))
.build();
Entity timeEntity = Entity.builder()
.attribute(timeAttribute)
.build();
Category environmentCategory = Category.builder(Categories.ENVIRONMENT)
.entity(timeEntity)
.build();
// ATM category
Attribute amountAttribute = Attribute.builder("urn:baeldung:atm:withdrawal:amount")
.value(DoubleExp.of("499.00"))
.build();
Entity atmEntity = Entity.builder()
.attribute(amountAttribute)
.build();
Category atmCategory = Category.builder(Categories.parse("urn:baeldung:atm:withdrawal"))
.entity(atmEntity)
.build();
RequestContext request = RequestContext.builder()
.attributes(actionCategory, environmentCategory, atmCategory)
.build();
ResponseContext response = pdp.decide(request);
assertNotNull(response);
assertTrue("Shoud have at least one result",
response.getResults() != null && !response.getResults().isEmpty());
Result result = response.getResults().iterator().next();
assertTrue("Evaluation should succeed", result.getStatus().isSuccess());
assertEquals("Should PERMIT withdrawal", Decision.PERMIT, result.getDecision());
}
@Test
public void testWhenBusinessHoursWithdrawalOver500_thenSuccess() throws Exception {
PolicyDecisionPoint pdp = buildPDP(POLICY_SET);
// Action category
Attribute actionAttribute = Attribute.builder("urn:oasis:names:tc:xacml:1.0:action:action-id")
.includeInResult(false)
.value(StringExp.of("withdrawal"))
.build();
Entity actionEntity = Entity.builder()
.attribute(actionAttribute)
.build();
Category actionCategory = Category.builder(Categories.ACTION)
.entity(actionEntity)
.build();
// Environment Category
Attribute timeAttribute = Attribute.builder("urn:oasis:names:tc:xacml:1.0:environment:current-time")
.includeInResult(false)
.value(TimeExp.of("12:00:00"))
.build();
Entity timeEntity = Entity.builder()
.attribute(timeAttribute)
.build();
Category environmentCategory = Category.builder(Categories.ENVIRONMENT)
.entity(timeEntity)
.build();
// ATM category
Attribute amountAttribute = Attribute.builder("urn:baeldung:atm:withdrawal:amount")
.value(DoubleExp.of("2000.00"))
.build();
Entity atmEntity = Entity.builder()
.attribute(amountAttribute)
.build();
Category atmCategory = Category.builder(Categories.parse("urn:baeldung:atm:withdrawal"))
.entity(atmEntity)
.build();
RequestContext request = RequestContext.builder()
.attributes(actionCategory, environmentCategory, atmCategory)
.build();
ResponseContext response = pdp.decide(request);
assertNotNull(response);
assertTrue("Shoud have at least one result", response.getResults() != null && !response.getResults()
.isEmpty());
Result result = response.getResults()
.iterator()
.next();
assertTrue("Evaluation should succeed", result.getStatus().isSuccess());
assertEquals("Should PERMIT withdrawal", Decision.PERMIT, result.getDecision());
}
private PolicyDecisionPoint buildPDP(String... policyResources) throws Exception {
PolicyRepository repository = new InMemoryPolicyRepository("tes-repository", FunctionProviderBuilder.builder()
.defaultFunctions()
.build(),
DecisionCombiningAlgorithmProviderBuilder.builder()
.withDefaultAlgorithms()
.create());
List<CompositeDecisionRule> policies = new ArrayList<CompositeDecisionRule>(policyResources.length);
for (String policyResource : policyResources) {
CompositeDecisionRule policy = repository.importPolicy(Xacml20TestUtility.getClasspathResource(policyResource));
log.info("Policy: {}", policy);
policies.add(policy);
}
return PolicyDecisionPointBuilder.builder("testPdp")
.policyRepository(repository)
.pip(PolicyInformationPointBuilder.builder("testPip")
.defaultResolvers()
.build())
.rootPolicy(policies.get(0))
.build();
}
}

View File

@ -0,0 +1,137 @@
<?xml version="1.0" encoding="UTF-8"?>
<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17 http://docs.oasis-open.org/xacml/3.0/xacml-core-v3-schema-wd-17.xsd"
PolicyId="urn:baeldung:atm:WithdrawalPolicy"
Version="1.0"
RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides">
<Description>
Withdrawal policy example
</Description>
<Target/>
<Rule RuleId="urn:oasis:names:tc:baeldung:WithDrawalPolicy:Rule1" Effect="Deny">
<Description>
Deny withdrawals over $500 between 20:00 and 08:00
</Description>
<Target>
<AnyOf>
<AllOf>
<Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">withdrawal</AttributeValue>
<AttributeDesignator
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="true"
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"/>
</Match>
</AllOf>
</AnyOf>
</Target>
<Condition>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:and">
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:not">
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-in-range">
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-one-and-only">
<AttributeDesignator
DataType="http://www.w3.org/2001/XMLSchema#time"
MustBePresent="true"
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment"
AttributeId="urn:oasis:names:tc:xacml:1.0:environment:current-time"/>
</Apply>
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">08:00:00</AttributeValue>
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">20:00:00</AttributeValue>
</Apply>
</Apply>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:double-greater-than">
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:double-one-and-only">
<AttributeDesignator
DataType="http://www.w3.org/2001/XMLSchema#double"
MustBePresent="true"
Category="urn:baeldung:atm:withdrawal"
AttributeId="urn:baeldung:atm:withdrawal:amount"/>
</Apply>
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#double">500.00</AttributeValue>
</Apply>
</Apply>
</Condition>
</Rule>
<Rule RuleId="urn:oasis:names:tc:baeldung:WithDrawalPolicy:Rule2" Effect="Permit">
<Description>
Permit withdrawals under $500 between 20:00 and 08:00
</Description>
<Target>
<AnyOf>
<AllOf>
<Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">withdrawal</AttributeValue>
<AttributeDesignator
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="true"
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"/>
</Match>
</AllOf>
</AnyOf>
</Target>
<Condition>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:and">
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:not">
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-in-range">
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-one-and-only">
<AttributeDesignator
DataType="http://www.w3.org/2001/XMLSchema#time"
MustBePresent="true"
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment"
AttributeId="urn:oasis:names:tc:xacml:1.0:environment:current-time"/>
</Apply>
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">08:00:00</AttributeValue>
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">20:00:00</AttributeValue>
</Apply>
</Apply>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:double-less-than-or-equal">
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:double-one-and-only">
<AttributeDesignator
DataType="http://www.w3.org/2001/XMLSchema#double"
MustBePresent="true"
Category="urn:baeldung:atm:withdrawal"
AttributeId="urn:baeldung:atm:withdrawal:amount"/>
</Apply>
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#double">500.00</AttributeValue>
</Apply>
</Apply>
</Condition>
</Rule>
<Rule RuleId="urn:oasis:names:tc:baeldung:WithDrawalPolicy:Rule3" Effect="Permit">
<Description>
Permit withdrawals of any value between 08:00 and 20:00
</Description>
<Target>
<AnyOf>
<AllOf>
<Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">withdrawal</AttributeValue>
<AttributeDesignator
DataType="http://www.w3.org/2001/XMLSchema#string"
MustBePresent="true"
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"/>
</Match>
</AllOf>
</AnyOf>
</Target>
<Condition>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-in-range">
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-one-and-only">
<AttributeDesignator
DataType="http://www.w3.org/2001/XMLSchema#time"
MustBePresent="true"
Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment"
AttributeId="urn:oasis:names:tc:xacml:1.0:environment:current-time"/>
</Apply>
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">08:00:00</AttributeValue>
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">20:00:00</AttributeValue>
</Apply>
</Condition>
</Rule>
</Policy>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<Request
xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17 http://docs.oasis-open.org/xacml/3.0/xacml-core-v3-schema-wd-17.xsd"
CombinedDecision="true"
ReturnPolicyIdList="false">
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
<Attribute
IncludeInResult="false"
AttributeId="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">withdrawal</AttributeValue>
</Attribute>
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
<Attribute
IncludeInResult="false"
AttributeId="urn:oasis:names:tc:xacml:1.0:environment:current-time">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">21:00:00</AttributeValue>
</Attribute>
</Attributes>
<Attributes Category="urn:baeldung:atm:withdrawal">
<Attribute
IncludeInResult="false"
AttributeId="urn:baeldung:atm:withdrawal:amount">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#decimal">1200</AttributeValue>
</Attribute>
</Attributes>
</Request>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<Response xmlns="urn:oasis:names:tc:xacml:2.0:context:schema:os" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xacml:2.0:context:schema:os http://docs.oasis-open.org/xacml/access_control-xacml-2.0-context-schema-os.xsd">
<Result>
<Decision>NotApplicable</Decision>
<Status>
<StatusCode Value="urn:oasis:names:tc:xacml:1.0:status:ok"/>
</Status>
</Result>
</Response>

View File

@ -40,6 +40,11 @@
<artifactId>javatuples</artifactId> <artifactId>javatuples</artifactId>
<version>${javatuples.version}</version> <version>${javatuples.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>${javaassist.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.assertj/assertj-core --> <!-- https://mvnrepository.com/artifact/org.assertj/assertj-core -->
<dependency> <dependency>
<groupId>org.assertj</groupId> <groupId>org.assertj</groupId>
@ -51,42 +56,6 @@
<artifactId>javers-core</artifactId> <artifactId>javers-core</artifactId>
<version>${javers.version}</version> <version>${javers.version}</version>
</dependency> </dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-core</artifactId>
<version>${serenity.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-junit</artifactId>
<version>${serenity.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-jbehave</artifactId>
<version>${serenity.jbehave.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-rest-assured</artifactId>
<version>${serenity.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-jira-requirements-provider</artifactId>
<version>${serenity.jira.version}</version>
<scope>test</scope>
</dependency>
<!-- JDO --> <!-- JDO -->
<dependency> <dependency>
<groupId>org.datanucleus</groupId> <groupId>org.datanucleus</groupId>
@ -139,30 +108,6 @@
<artifactId>spring-web</artifactId> <artifactId>spring-web</artifactId>
<version>${spring.version}</version> <version>${spring.version}</version>
</dependency> </dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-spring</artifactId>
<version>${serenity.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-screenplay</artifactId>
<version>${serenity.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-screenplay-webdriver</artifactId>
<version>${serenity.version}</version>
<scope>test</scope>
</dependency>
<!-- JetS3t --> <!-- JetS3t -->
<dependency> <dependency>
<groupId>org.lucee</groupId> <groupId>org.lucee</groupId>
@ -253,29 +198,6 @@
<build> <build>
<plugins> <plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<configuration>
<systemProperties>
<webdriver.chrome.driver>chromedriver</webdriver.chrome.driver>
</systemProperties>
</configuration>
</plugin>
<plugin>
<groupId>net.serenity-bdd.maven.plugins</groupId>
<artifactId>serenity-maven-plugin</artifactId>
<version>${serenity.plugin.version}</version>
<executions>
<execution>
<id>serenity-reports</id>
<phase>post-integration-test</phase>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- JDO Plugin --> <!-- JDO Plugin -->
<plugin> <plugin>
<groupId>org.datanucleus</groupId> <groupId>org.datanucleus</groupId>
@ -380,6 +302,7 @@
<spring.version>4.3.8.RELEASE</spring.version> <spring.version>4.3.8.RELEASE</spring.version>
<spring-mock-mvc.version>3.0.3</spring-mock-mvc.version> <spring-mock-mvc.version>3.0.3</spring-mock-mvc.version>
<quartz.version>2.3.0</quartz.version> <quartz.version>2.3.0</quartz.version>
<javaassist.version>3.21.0-GA</javaassist.version>
<jool.version>0.9.12</jool.version> <jool.version>0.9.12</jool.version>
<maven-jar-plugin.version>3.0.2</maven-jar-plugin.version> <maven-jar-plugin.version>3.0.2</maven-jar-plugin.version>
<commons-net.version>3.6</commons-net.version> <commons-net.version>3.6</commons-net.version>

View File

@ -1,4 +0,0 @@
jira.url=<jira-url>
jira.project=<jira-project>
jira.username=<jira-username>
jira.password=<jira-password>

View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [Understanding the "relativePath" Tag - Maven Parent POM Resolution At A Glance](https://www.baeldung.com/maven-relativepath)

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>maven-parent-pom-resolution</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>project-a</module>
</modules>
<!-- to detect the POM hierarchy, just type "mvn dependency:display-ancestors" -->
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.2.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@ -0,0 +1,20 @@
<?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>project-a</artifactId>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>maven-parent-pom-resolution</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- The parent pom is resolved to ../pom.xml -->
</parent>
<packaging>pom</packaging>
<modules>
<module>project-b</module>
<module>project-c</module>
</modules>
</project>

View File

@ -0,0 +1,15 @@
<?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>project-b</artifactId>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>project-a</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- The parent pom is resolved to project a's pom.xml -->
</parent>
<packaging>pom</packaging>
</project>

View File

@ -0,0 +1,20 @@
<?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>project-c</artifactId>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>project-b</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../project-b/pom.xml</relativePath>
<!-- The parent pom is resolved to project a's pom.xml -->
</parent>
<packaging>pom</packaging>
<modules>
<module>project-d</module>
</modules>
</project>

View File

@ -0,0 +1,17 @@
<?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>project-d</artifactId>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>project-a</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- removing relativePath won't work even if project-a is the aggregator project -->
<!-- it only works in IntelliJ IDEA when project-a is registered as a Maven Project -->
<relativePath>../../pom.xml</relativePath>
</parent>
<packaging>pom</packaging>
</project>

View File

@ -18,7 +18,7 @@
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.13</version> <version>${junit.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
@ -46,6 +46,7 @@
<properties> <properties>
<name>${project.name}</name> <name>${project.name}</name>
<my.awesome.property>property-from-pom</my.awesome.property> <my.awesome.property>property-from-pom</my.awesome.property>
<junit.version>4.13</junit.version>
</properties> </properties>
</project> </project>

View File

@ -0,0 +1,3 @@
## Relevant Articles:
- [Running a Single Test or Method With Maven](https://www.baeldung.com/maven-run-single-test)

View File

@ -36,6 +36,7 @@
<module>host-maven-repo-example</module> <module>host-maven-repo-example</module>
<module>plugin-management</module> <module>plugin-management</module>
<module>maven-surefire-plugin</module> <module>maven-surefire-plugin</module>
<module>maven-parent-pom-resolution</module>
</modules> </modules>
</project> </project>

View File

@ -30,7 +30,7 @@
</dependencies> </dependencies>
<properties> <properties>
<spring.version>5.3.7</spring.version> <spring.version>5.3.9</spring.version>
<spring-security.version>5.2.3.RELEASE</spring-security.version> <spring-security.version>5.2.3.RELEASE</spring-security.version>
<spring-boot-starter-test.version>1.5.10.RELEASE</spring-boot-starter-test.version> <spring-boot-starter-test.version>1.5.10.RELEASE</spring-boot-starter-test.version>
</properties> </properties>

View File

@ -3,3 +3,4 @@
- [The DAO Pattern in Java](https://www.baeldung.com/java-dao-pattern) - [The DAO Pattern in Java](https://www.baeldung.com/java-dao-pattern)
- [DAO vs Repository Patterns](https://www.baeldung.com/java-dao-vs-repository) - [DAO vs Repository Patterns](https://www.baeldung.com/java-dao-vs-repository)
- [Difference Between MVC and MVP Patterns](https://www.baeldung.com/mvc-vs-mvp-pattern) - [Difference Between MVC and MVP Patterns](https://www.baeldung.com/mvc-vs-mvp-pattern)
- [The DTO Pattern (Data Transfer Object)](https://www.baeldung.com/java-dto-pattern)

View File

@ -15,6 +15,21 @@
</parent> </parent>
<dependencies> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>${rest-assured.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.assertj</groupId> <groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId> <artifactId>assertj-core</artifactId>
@ -38,6 +53,9 @@
<assertj-core.version>3.9.1</assertj-core.version> <assertj-core.version>3.9.1</assertj-core.version>
<hibernate-core.version>5.2.16.Final</hibernate-core.version> <hibernate-core.version>5.2.16.Final</hibernate-core.version>
<mysql-connector.version>6.0.6</mysql-connector.version> <mysql-connector.version>6.0.6</mysql-connector.version>
<spring-boot.version>2.5.3</spring-boot.version>
<rest-assured.version>3.3.0</rest-assured.version>
</properties> </properties>
</project> </project>

View File

@ -0,0 +1,12 @@
package com.baeldung.dtopattern;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}

View File

@ -0,0 +1,28 @@
package com.baeldung.dtopattern.api;
import com.baeldung.dtopattern.domain.Role;
import com.baeldung.dtopattern.domain.User;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import static java.util.stream.Collectors.toList;
@Component
class Mapper {
public UserDTO toDto(User user) {
String name = user.getName();
List<String> roles = user
.getRoles()
.stream()
.map(Role::getName)
.collect(toList());
return new UserDTO(name, roles);
}
public User toUser(UserCreationDTO userDTO) {
return new User(userDTO.getName(), userDTO.getPassword(), new ArrayList<>());
}
}

View File

@ -0,0 +1,51 @@
package com.baeldung.dtopattern.api;
import com.baeldung.dtopattern.domain.RoleService;
import com.baeldung.dtopattern.domain.User;
import com.baeldung.dtopattern.domain.UserService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static java.util.stream.Collectors.toList;
@RestController
@RequestMapping("/users")
class UserController {
private UserService userService;
private RoleService roleService;
private Mapper mapper;
public UserController(UserService userService, RoleService roleService, Mapper mapper) {
this.userService = userService;
this.roleService = roleService;
this.mapper = mapper;
}
@GetMapping
@ResponseBody
public List<UserDTO> getUsers() {
return userService.getAll()
.stream()
.map(mapper::toDto)
.collect(toList());
}
@PostMapping
@ResponseBody
public UserIdDTO create(@RequestBody UserCreationDTO userDTO) {
User user = mapper.toUser(userDTO);
userDTO.getRoles()
.stream()
.map(role -> roleService.getOrCreate(role))
.forEach(user::addRole);
userService.save(user);
return new UserIdDTO(user.getId());
}
}

View File

@ -0,0 +1,36 @@
package com.baeldung.dtopattern.api;
import java.util.List;
public class UserCreationDTO {
private String name;
private String password;
private List<String> roles;
UserCreationDTO() {}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
public List<String> getRoles() {
return roles;
}
void setName(String name) {
this.name = name;
}
void setPassword(String password) {
this.password = password;
}
void setRoles(List<String> roles) {
this.roles = roles;
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.dtopattern.api;
import java.util.List;
public class UserDTO {
private String name;
private List<String> roles;
public UserDTO(String name, List<String> roles) {
this.name = name;
this.roles = roles;
}
public String getName() {
return name;
}
public List<String> getRoles() {
return roles;
}
}

View File

@ -0,0 +1,14 @@
package com.baeldung.dtopattern.api;
public class UserIdDTO {
private String id;
public UserIdDTO(String id) {
this.id = id;
}
public String getId() {
return id;
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.dtopattern.domain;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
class InMemoryRepository implements UserRepository, RoleRepository {
private Map<String, User> users = new LinkedHashMap<>();
private Map<String, Role> roles = new LinkedHashMap<>();
@Override
public List<User> getAll() {
return new ArrayList<>(users.values());
}
@Override
public void save(User user) {
user.setId(UUID.randomUUID().toString());
users.put(user.getId(), user);
}
@Override
public void save(Role role) {
role.setId(UUID.randomUUID().toString());
roles.put(role.getId(), role);
}
@Override
public Role getRoleById(String id) {
return roles.get(id);
}
@Override
public Role getRoleByName(String name) {
return roles.values()
.stream()
.filter(role -> role.getName().equalsIgnoreCase(name))
.findFirst()
.orElse(null);
}
@Override
public void deleteAll() {
users.clear();
roles.clear();
}
}

View File

@ -0,0 +1,28 @@
package com.baeldung.dtopattern.domain;
import java.util.Objects;
public class Role {
private String id;
private String name;
public Role(String name) {
this.name = Objects.requireNonNull(name);
}
public String getId() {
return id;
}
void setId(String id) {
this.id = Objects.requireNonNull(id);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = Objects.requireNonNull(name);
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.dtopattern.domain;
public interface RoleRepository {
Role getRoleById(String id);
Role getRoleByName(String name);
void save(Role role);
}

View File

@ -0,0 +1,32 @@
package com.baeldung.dtopattern.domain;
import org.springframework.stereotype.Service;
import java.util.Objects;
@Service
public class RoleService {
private RoleRepository repository;
public RoleService(RoleRepository repository) {
this.repository = repository;
}
public Role getOrCreate(String name) {
Role role = repository.getRoleByName(name);
if (role == null) {
role = new Role(name);
repository.save(role);
}
return role;
}
public void save(Role role) {
Objects.requireNonNull(role);
repository.save(role);
}
}

View File

@ -0,0 +1,80 @@
package com.baeldung.dtopattern.domain;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class User {
private static SecretKeySpec KEY = initKey();
static SecretKeySpec initKey(){
try {
SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey();
return new SecretKeySpec(secretKey.getEncoded(), "AES");
} catch (NoSuchAlgorithmException ex) {
return null;
}
}
private String id;
private String name;
private String password;
private List<Role> roles;
public User(String name, String password, List<Role> roles) {
this.name = Objects.requireNonNull(name);
this.password = this.encrypt(password);
this.roles = Objects.requireNonNull(roles);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void addRole(Role role) {
roles.add(role);
}
public List<Role> getRoles() {
return Collections.unmodifiableList(roles);
}
public String getId() {
return id;
}
void setId(String id) {
this.id = id;
}
String encrypt(String password) {
Objects.requireNonNull(password);
try {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, KEY);
final byte[] encryptedBytes = cipher.doFinal(password.getBytes(StandardCharsets.UTF_8));
return new String(encryptedBytes, StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
// do nothing
return "";
}
}
}

View File

@ -0,0 +1,9 @@
package com.baeldung.dtopattern.domain;
import java.util.List;
public interface UserRepository {
List<User> getAll();
void save(User user);
void deleteAll();
}

View File

@ -0,0 +1,25 @@
package com.baeldung.dtopattern.domain;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
@Service
public class UserService {
private UserRepository repository;
public UserService(UserRepository repository) {
this.repository = repository;
}
public List<User> getAll() {
return repository.getAll();
}
public void save(User user) {
Objects.requireNonNull(user);
repository.save(user);
}
}

View File

@ -0,0 +1,56 @@
package com.baeldung.dtopattern.api;
import com.baeldung.dtopattern.domain.Role;
import com.baeldung.dtopattern.domain.User;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class MapperUnitTest {
@Test
void toDto_shouldMapFromDomainToDTO() {
String name = "Test";
String password = "test";
Role admin = new Role("admin");
List<String> expectedRoles = Collections.singletonList("admin");
List<Role> roles = new ArrayList<>();
roles.add(admin);
User user = new User(name, password, roles);
Mapper mapper = new Mapper();
UserDTO dto = mapper.toDto(user);
assertEquals(name, dto.getName());
assertEquals(expectedRoles, dto.getRoles());
}
@Test
void toUser_shouldMapFromDTOToDomain() {
String name = "Test";
String password = "test";
String role = "admin";
UserCreationDTO dto = new UserCreationDTO();
dto.setName(name);
dto.setPassword(password);
dto.setRoles(Collections.singletonList("admin"));
User expectedUser = new User(name, password, new ArrayList<>());
Mapper mapper = new Mapper();
User user = mapper.toUser(dto);
assertEquals(name, user.getName());
assertEquals(expectedUser.getPassword(), user.getPassword());
assertEquals(Collections.emptyList(), user.getRoles());
}
}

View File

@ -0,0 +1,80 @@
package com.baeldung.dtopattern.api;
import com.baeldung.dtopattern.domain.Role;
import com.baeldung.dtopattern.domain.RoleRepository;
import com.baeldung.dtopattern.domain.User;
import com.baeldung.dtopattern.domain.UserRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import java.util.Collections;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.*;
import static org.springframework.http.HttpStatus.OK;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserControllerIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@LocalServerPort
int port;
@Autowired
private ObjectMapper objectMapper;
@Test
void create_shouldReturnUseId() throws Exception {
UserCreationDTO request = new UserCreationDTO();
request.setName("User 1");
request.setPassword("Test@123456");
request.setRoles(Collections.singletonList("admin"));
given()
.contentType(ContentType.JSON)
.body(objectMapper.writeValueAsString(request))
.when()
.port(port)
.post("/users")
.then()
.statusCode(OK.value())
.body("id", notNullValue());
}
@Test
void getAll_shouldReturnUseDTO() {
userRepository.deleteAll();
String roleName = "admin";
Role admin = new Role(roleName);
roleRepository.save(admin);
String name = "User 1";
User user = new User(name, "Test@123456", Collections.singletonList(admin));
userRepository.save(user);
given()
.port(port)
.when()
.get("/users")
.then()
.statusCode(OK.value())
.body("size()", is(1))
.body("[0].name", equalTo(name))
.body("[0].roles", hasItem(roleName));
}
}

View File

@ -0,0 +1,83 @@
package com.baeldung.dtopattern.domain;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class InMemoryRepositoryUnitTest {
@Test
void getAll_shouldReturnAllUsers() {
String name = "Test";
String password = "test123";
List<Role> roles = new ArrayList<>();
User user = new User(name, password, roles);
List<User> expectedUsers = Collections.singletonList(user);
InMemoryRepository repository = new InMemoryRepository();
repository.save(user);
List<User> users = repository.getAll();
assertEquals(expectedUsers, users);
}
@Test
void save_whenSavingUser_shouldSetId() {
String name = "Test";
String password = "test123";
List<Role> roles = new ArrayList<>();
User user = new User(name, password, roles);
InMemoryRepository repository = new InMemoryRepository();
repository.save(user);
assertNotNull(user.getId());
}
@Test
void save_whenSavingRole_shouldSetId() {
String name = "Test";
Role role = new Role(name);
InMemoryRepository repository = new InMemoryRepository();
repository.save(role);
assertNotNull(role.getId());
}
@Test
void getRoleById_shouldReturnRoleById() {
String name = "Test";
Role expectedRole = new Role(name);
InMemoryRepository repository = new InMemoryRepository();
repository.save(expectedRole);
Role role = repository.getRoleById(expectedRole.getId());
assertEquals(expectedRole, role);
}
@Test
void getRoleByName_shouldReturnRoleByName() {
String name = "Test";
Role expectedRole = new Role(name);
InMemoryRepository repository = new InMemoryRepository();
repository.save(expectedRole);
Role role = repository.getRoleByName(name);
assertEquals(expectedRole, role);
}
}

View File

@ -0,0 +1,38 @@
package com.baeldung.dtopattern.domain;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import static org.junit.jupiter.api.Assertions.*;
class UserUnitTest {
@Test
void whenUserIsCreated_shouldEncryptPassword() {
User user = new User("Test", "test", new ArrayList<>());
assertEquals(user.encrypt("test"), user.getPassword());
assertNotEquals(user.encrypt("Test"), user.getPassword());
}
@Test
void whenUserIsCreated_shouldFailIfNameIsNull() {
assertThrows(NullPointerException.class, () ->
new User(null, "test", new ArrayList<>()));
}
@Test
void whenUserIsCreated_shouldFailIfPasswordIsNull() {
assertThrows(NullPointerException.class, () ->
new User("Test", null, new ArrayList<>()));
}
@Test
void whenUserIsCreated_shouldFailIfRolesIsNull() {
assertThrows(NullPointerException.class, () ->
new User("Test", "Test", null));
}
}

View File

@ -13,3 +13,4 @@ This module contains articles about the Java Persistence API (JPA) in Java.
- [Returning an Auto-Generated Id with JPA](https://www.baeldung.com/jpa-get-auto-generated-id) - [Returning an Auto-Generated Id with JPA](https://www.baeldung.com/jpa-get-auto-generated-id)
- [How to Return Multiple Entities In JPA Query](https://www.baeldung.com/jpa-return-multiple-entities) - [How to Return Multiple Entities In JPA Query](https://www.baeldung.com/jpa-return-multiple-entities)
- [Defining Unique Constraints in JPA](https://www.baeldung.com/jpa-unique-constraints) - [Defining Unique Constraints in JPA](https://www.baeldung.com/jpa-unique-constraints)
- [How to Check Field Existence in MongoDB?](https://www.baeldung.com/mongodb-check-field-exists)

View File

@ -11,3 +11,4 @@ This module contains articles about Reactor Core.
- [How to Convert Mono<List<T\>> Into Flux<T\>](https://www.baeldung.com/java-mono-list-to-flux) - [How to Convert Mono<List<T\>> Into Flux<T\>](https://www.baeldung.com/java-mono-list-to-flux)
- [Project Reactor: map() vs flatMap()](https://www.baeldung.com/java-reactor-map-flatmap) - [Project Reactor: map() vs flatMap()](https://www.baeldung.com/java-reactor-map-flatmap)
- [What Does Mono.defer() Do?](https://www.baeldung.com/java-mono-defer) - [What Does Mono.defer() Do?](https://www.baeldung.com/java-mono-defer)
- [Handling Exceptions in Project Reactor](https://www.baeldung.com/reactor-exceptions)

View File

@ -41,7 +41,7 @@
</dependencies> </dependencies>
<properties> <properties>
<reactor.version>3.3.9.RELEASE</reactor.version> <reactor.version>3.4.9</reactor.version>
<assertj.version>3.6.1</assertj.version> <assertj.version>3.6.1</assertj.version>
</properties> </properties>

View File

@ -0,0 +1,89 @@
package com.baeldung.reactor.exception;
import org.junit.Test;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.SynchronousSink;
import reactor.test.StepVerifier;
import java.util.function.BiConsumer;
import java.util.function.Function;
public class ExceptionUnitTest {
@Test
public void givenInvalidElement_whenPipelineThrowsException_thenErrorIsSentDownstream() {
Function<String, Integer> mapper = input -> {
if (input.matches("\\D")) {
throw new NumberFormatException();
} else {
return Integer.parseInt(input);
}
};
Flux<String> inFlux = Flux.just("1", "1.5", "2");
Flux<Integer> outFlux = inFlux.map(mapper);
StepVerifier.create(outFlux)
.expectNext(1)
.expectError(NumberFormatException.class)
.verify();
}
@Test
public void givenInvalidElement_whenHandleCallsSinkErrorMethod_thenErrorIsSentDownstream() {
BiConsumer<String, SynchronousSink<Integer>> handler = (input, sink) -> {
if (input.matches("\\D")) {
sink.error(new NumberFormatException());
} else {
sink.next(Integer.parseInt(input));
}
};
Flux<String> inFlux = Flux.just("1", "1.5", "2");
Flux<Integer> outFlux = inFlux.handle(handler);
StepVerifier.create(outFlux)
.expectNext(1)
.expectError(NumberFormatException.class)
.verify();
}
@Test
public void givenInvalidElement_whenFlatMapCallsMonoErrorMethod_thenErrorIsSentDownstream() {
Function<String, Publisher<Integer>> mapper = input -> {
if (input.matches("\\D")) {
return Mono.error(new NumberFormatException());
} else {
return Mono.just(Integer.parseInt(input));
}
};
Flux<String> inFlux = Flux.just("1", "1.5", "2");
Flux<Integer> outFlux = inFlux.flatMap(mapper);
StepVerifier.create(outFlux)
.expectNext(1)
.expectError(NumberFormatException.class)
.verify();
}
@Test
public void givenNullElement_whenPipelineOperatorExecutes_thenNpeIsSentDownstream() {
Function<String, Integer> mapper = input -> {
if (input == null) {
return 0;
} else {
return Integer.parseInt(input);
}
};
Flux<String> inFlux = Flux.just("1", null, "2");
Flux<Integer> outFlux = inFlux.map(mapper);
StepVerifier.create(outFlux)
.expectNext(1)
.expectError(NullPointerException.class)
.verify();
}
}

View File

@ -8,6 +8,7 @@ This module contains articles about Spring with Kafka
- [Testing Kafka and Spring Boot](https://www.baeldung.com/spring-boot-kafka-testing) - [Testing Kafka and Spring Boot](https://www.baeldung.com/spring-boot-kafka-testing)
- [Monitor the Consumer Lag in Apache Kafka](https://www.baeldung.com/java-kafka-consumer-lag) - [Monitor the Consumer Lag in Apache Kafka](https://www.baeldung.com/java-kafka-consumer-lag)
- [Send Large Messages With Kafka](https://www.baeldung.com/java-kafka-send-large-message) - [Send Large Messages With Kafka](https://www.baeldung.com/java-kafka-send-large-message)
- [Configuring Kafka SSL Using Spring Boot](https://www.baeldung.com/spring-boot-kafka-ssl)
### Intro ### Intro

View File

@ -28,6 +28,10 @@
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.kafka</groupId> <groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka-test</artifactId> <artifactId>spring-kafka-test</artifactId>
@ -41,9 +45,15 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-collections</groupId> <groupId>org.testcontainers</groupId>
<artifactId>commons-collections</artifactId> <artifactId>junit-jupiter</artifactId>
<version>3.2.1</version> <version>${testcontainers-kafka.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -0,0 +1,25 @@
package com.baeldung.kafka.ssl;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
@Slf4j
public class KafkaConsumer {
public static final String TOPIC = "test-topic";
public final List<String> messages = new ArrayList<>();
@KafkaListener(topics = TOPIC)
public void receive(ConsumerRecord<String, String> consumerRecord) {
log.info("Received payload: '{}'", consumerRecord.toString());
messages.add(consumerRecord.value());
}
}

View File

@ -0,0 +1,23 @@
package com.baeldung.kafka.ssl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
@Slf4j
@AllArgsConstructor
@Component
public class KafkaProducer {
private final KafkaTemplate<String, String> kafkaTemplate;
public void sendMessage(String message, String topic) {
log.info("Producing message: {}", message);
kafkaTemplate.send(topic, "key", message)
.addCallback(
result -> log.info("Message sent to topic: {}", message),
ex -> log.error("Failed to send message", ex)
);
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.kafka.ssl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableAutoConfiguration
public class KafkaSslApplication {
public static void main(String[] args) {
SpringApplication.run(KafkaSslApplication.class, args);
}
}

View File

@ -0,0 +1,18 @@
spring:
kafka:
security:
protocol: "SSL"
bootstrap-servers: localhost:9093
ssl:
trust-store-location: classpath:/client-certs/kafka.client.truststore.jks
trust-store-password: password
key-store-location: classpath:/client-certs/kafka.client.keystore.jks
key-store-password: password
consumer:
group-id: demo-group-id
auto-offset-reset: earliest
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
producer:
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

View File

@ -0,0 +1,54 @@
package com.baeldung.kafka.ssl;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.testcontainers.containers.DockerComposeContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.io.File;
import java.time.Duration;
import java.util.UUID;
import static com.baeldung.kafka.ssl.KafkaConsumer.TOPIC;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
@Slf4j
@ActiveProfiles("ssl")
@Testcontainers
@SpringBootTest(classes = KafkaSslApplication.class)
class KafkaSslApplicationLiveTest {
private static final File KAFKA_COMPOSE_FILE = new File("src/test/resources/docker/docker-compose.yml");
private static final String KAFKA_SERVICE = "kafka";
private static final int SSL_PORT = 9093;
@Container
public DockerComposeContainer<?> container =
new DockerComposeContainer<>(KAFKA_COMPOSE_FILE)
.withExposedService(KAFKA_SERVICE, SSL_PORT, Wait.forListeningPort());
@Autowired
private KafkaProducer kafkaProducer;
@Autowired
private KafkaConsumer kafkaConsumer;
@Test
void givenSslIsConfigured_whenProducerSendsMessageOverSsl_thenConsumerReceivesOverSsl() {
String message = generateSampleMessage();
kafkaProducer.sendMessage(message, TOPIC);
await().atMost(Duration.ofMinutes(2))
.untilAsserted(() -> assertThat(kafkaConsumer.messages).containsExactly(message));
}
private static String generateSampleMessage() {
return UUID.randomUUID().toString();
}
}

View File

@ -0,0 +1 @@
password

View File

@ -0,0 +1 @@
password

View File

@ -0,0 +1 @@
password

View File

@ -0,0 +1,30 @@
---
version: '2'
services:
zookeeper:
image: confluentinc/cp-zookeeper:6.2.0
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
kafka:
image: confluentinc/cp-kafka:6.2.0
depends_on:
- zookeeper
ports:
- 9092:9092
- 9093:9093
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092,SSL://localhost:9093
KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_SSL_CLIENT_AUTH: "required"
KAFKA_SSL_KEYSTORE_FILENAME: '/certs/kafka.server.keystore.jks'
KAFKA_SSL_KEYSTORE_CREDENTIALS: '/certs/kafka_keystore_credentials'
KAFKA_SSL_KEY_CREDENTIALS: '/certs/kafka_sslkey_credentials'
KAFKA_SSL_TRUSTSTORE_FILENAME: '/certs/kafka.server.truststore.jks'
KAFKA_SSL_TRUSTSTORE_CREDENTIALS: '/certs/kafka_truststore_credentials'
volumes:
- ./certs/:/etc/kafka/secrets/certs

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