Merge branch 'master' into JAVA-11196-split-httpclient-module

This commit is contained in:
kwoyke 2022-04-06 14:00:30 +02:00 committed by GitHub
commit db29759c69
84 changed files with 1544 additions and 802 deletions

View File

@ -12,3 +12,4 @@ This module contains articles about parsing and formatting Java date and time ob
- [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)
- [Format a Milliseconds Duration to HH:MM:SS](https://www.baeldung.com/java-ms-to-hhmmss)
- [Format Instant to String in Java](https://www.baeldung.com/java-instant-to-string)

View File

@ -0,0 +1,60 @@
package com.baeldung.implementsvsextends;
import com.baeldung.implementsvsextends.media.model.AudioMedia;
import com.baeldung.implementsvsextends.media.model.Media;
import com.baeldung.implementsvsextends.media.model.VideoMedia;
import com.baeldung.implementsvsextends.media.player.impl.AudioMediaPlayer;
import com.baeldung.implementsvsextends.media.player.impl.CustomMediaPlayer;
import com.baeldung.implementsvsextends.media.player.impl.MultiMediaPlayer;
import com.baeldung.implementsvsextends.media.player.impl.VideoMediaPlayer;
public class Main {
public static void main(String[] args) {
Media media = new Media();
media.setId(001);
media.setTitle("Media1");
media.setArtist("Artist001");
AudioMedia audioMedia = new AudioMedia();
audioMedia.setId(101);
audioMedia.setTitle("Audio1");
audioMedia.setArtist("Artist101");
audioMedia.setBitrate(3500);
audioMedia.setFrequency("256kbps");
VideoMedia videoMedia = new VideoMedia();
videoMedia.setId(201);
videoMedia.setTitle("Video1");
videoMedia.setArtist("Artist201");
videoMedia.setResolution("1024x768");
videoMedia.setAspectRatio("16:9");
System.out.println(media);
System.out.println(audioMedia);
System.out.println(videoMedia);
AudioMediaPlayer audioMediaPlayer = new AudioMediaPlayer();
audioMediaPlayer.play();
audioMediaPlayer.pause();
VideoMediaPlayer videoMediaPlayer = new VideoMediaPlayer();
videoMediaPlayer.play();
videoMediaPlayer.pause();
MultiMediaPlayer multiMediaPlayer = new MultiMediaPlayer();
multiMediaPlayer.play();
multiMediaPlayer.pause();
multiMediaPlayer.seek();
multiMediaPlayer.fastForward();
CustomMediaPlayer customMediaPlayer = new CustomMediaPlayer();
customMediaPlayer.play();
customMediaPlayer.pause();
customMediaPlayer.setId(301);
customMediaPlayer.setTitle("Custom1");
customMediaPlayer.setArtist("Artist301");
System.out.println(customMediaPlayer);
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.implementsvsextends.media.model;
public class AudioMedia extends Media {
private int bitrate;
private String frequency;
@Override
public void printTitle() {
System.out.println("AudioMedia Title");
}
public int getBitrate() {
return bitrate;
}
public void setBitrate(int bitrate) {
this.bitrate = bitrate;
}
public String getFrequency() {
return frequency;
}
public void setFrequency(String frequency) {
this.frequency = frequency;
}
@Override
public String toString() {
return "AudioMedia{" +
"id=" + this.getId() +
", title='" + this.getTitle() + '\'' +
", artist='" + this.getArtist() + '\'' +
", bitrate=" + bitrate +
", frequency='" + frequency + '\'' +
"} ";
}
}

View File

@ -0,0 +1,47 @@
package com.baeldung.implementsvsextends.media.model;
public class Media {
private int id;
private String title;
private String artist;
public void printTitle() {
System.out.println("Media Title");
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
@Override
public String toString() {
return "Media{" +
"id=" + id +
", title='" + title + '\'' +
", artist='" + artist + '\'' +
'}';
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.implementsvsextends.media.model;
public class VideoMedia extends Media {
private String resolution;
private String aspectRatio;
public String getResolution() {
return resolution;
}
public void setResolution(String resolution) {
this.resolution = resolution;
}
public String getAspectRatio() {
return aspectRatio;
}
public void setAspectRatio(String aspectRatio) {
this.aspectRatio = aspectRatio;
}
@Override
public String toString() {
return "VideoMedia{" +
"id=" + this.getId() +
", title='" + this.getTitle() + '\'' +
", artist='" + this.getArtist() + '\'' +
"resolution='" + resolution + '\'' +
", aspectRatio='" + aspectRatio + '\'' +
"} ";
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.implementsvsextends.media.player;
public interface AdvancedPlayerOptions {
void seek();
void fastForward();
}

View File

@ -0,0 +1,8 @@
package com.baeldung.implementsvsextends.media.player;
public interface MediaPlayer {
void play();
void pause();
}

View File

@ -0,0 +1,16 @@
package com.baeldung.implementsvsextends.media.player.impl;
import com.baeldung.implementsvsextends.media.player.MediaPlayer;
public class AudioMediaPlayer implements MediaPlayer {
@Override
public void play() {
System.out.println("AudioMediaPlayer is Playing");
}
@Override
public void pause() {
System.out.println("AudioMediaPlayer is Paused");
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.implementsvsextends.media.player.impl;
import com.baeldung.implementsvsextends.media.model.Media;
import com.baeldung.implementsvsextends.media.player.MediaPlayer;
public class CustomMediaPlayer extends Media implements MediaPlayer {
@Override
public void play() {
System.out.println("CustomMediaPlayer is Playing");
}
@Override
public void pause() {
System.out.println("CustomMediaPlayer is Paused");
}
}

View File

@ -0,0 +1,27 @@
package com.baeldung.implementsvsextends.media.player.impl;
import com.baeldung.implementsvsextends.media.player.AdvancedPlayerOptions;
import com.baeldung.implementsvsextends.media.player.MediaPlayer;
public class MultiMediaPlayer implements MediaPlayer, AdvancedPlayerOptions {
@Override
public void play() {
System.out.println("MultiMediaPlayer is Playing");
}
@Override
public void pause() {
System.out.println("MultiMediaPlayer is Paused");
}
@Override
public void seek() {
System.out.println("MultiMediaPlayer is being seeked");
}
@Override
public void fastForward() {
System.out.println("MultiMediaPlayer is being fast forwarded");
}
}

View File

@ -0,0 +1,16 @@
package com.baeldung.implementsvsextends.media.player.impl;
import com.baeldung.implementsvsextends.media.player.MediaPlayer;
public class VideoMediaPlayer implements MediaPlayer {
@Override
public void play() {
System.out.println("VideoMediaPlayer is Playing");
}
@Override
public void pause() {
System.out.println("VideoMediaPlayer is Paused");
}
}

View File

@ -0,0 +1,14 @@
package com.baeldung.implementsvsextends.media.model;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Test;
public class AudioMediaUnitTest {
@Test
public void givenAudioMediaInstance_whenCheckedType_thenIsInstanceOfMedia() {
AudioMedia audioMedia = new AudioMedia();
Assert.assertThat(audioMedia, CoreMatchers.<AudioMedia>instanceOf(Media.class));
}
}

View File

@ -0,0 +1,14 @@
package com.baeldung.implementsvsextends.media.model;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Test;
public class VideoMediaUnitTest {
@Test
public void givenVideoMediaInstance_whenCheckedType_thenIsInstanceOfMedia() {
VideoMedia videoMedia = new VideoMedia();
Assert.assertThat(videoMedia, CoreMatchers.<VideoMedia>instanceOf(Media.class));
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.implementsvsextends.media.player.impl;
import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
public class AudioMediaPlayerUnitTest {
private final PrintStream standardOut = System.out;
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
@BeforeEach
public void setUp() {
System.setOut(new PrintStream(outputStreamCaptor));
}
@AfterEach
public void tearDown() {
System.setOut(standardOut);
}
@Test
public void givenAudioMediaPlayer_whenPlay_thenPrintsPlayingString() {
AudioMediaPlayer audioMediaPlayer = new AudioMediaPlayer();
audioMediaPlayer.play();
Assert.assertEquals("AudioMediaPlayer is Playing", outputStreamCaptor.toString()
.trim());
}
@Test
public void givenAudioMediaPlayer_whenPause_thenPrintsPausedString() {
AudioMediaPlayer audioMediaPlayer = new AudioMediaPlayer();
audioMediaPlayer.pause();
Assert.assertEquals("AudioMediaPlayer is Paused", outputStreamCaptor.toString()
.trim());
}
}

View File

@ -0,0 +1,58 @@
package com.baeldung.implementsvsextends.media.player.impl;
import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
public class MultiMediaPlayerUnitTest {
private final PrintStream standardOut = System.out;
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
@BeforeEach
public void setUp() {
System.setOut(new PrintStream(outputStreamCaptor));
}
@AfterEach
public void tearDown() {
System.setOut(standardOut);
}
@Test
public void givenMultiMediaPlayer_whenPlay_thenPrintsPlayingString() {
MultiMediaPlayer multiMediaPlayer = new MultiMediaPlayer();
multiMediaPlayer.play();
Assert.assertEquals("MultiMediaPlayer is Playing", outputStreamCaptor.toString()
.trim());
}
@Test
public void givenMultiMediaPlayer_whenPause_thenPrintsPausedString() {
MultiMediaPlayer multiMediaPlayer = new MultiMediaPlayer();
multiMediaPlayer.pause();
Assert.assertEquals("MultiMediaPlayer is Paused", outputStreamCaptor.toString()
.trim());
}
@Test
public void givenMultiMediaPlayer_whenSeek_thenPrintsPausedString() {
MultiMediaPlayer multiMediaPlayer = new MultiMediaPlayer();
multiMediaPlayer.seek();
Assert.assertEquals("MultiMediaPlayer is being seeked", outputStreamCaptor.toString()
.trim());
}
@Test
public void givenMultiMediaPlayer_whenFastForward_thenPrintsPausedString() {
MultiMediaPlayer multiMediaPlayer = new MultiMediaPlayer();
multiMediaPlayer.fastForward();
Assert.assertEquals("MultiMediaPlayer is being fast forwarded",
outputStreamCaptor.toString()
.trim());
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.implementsvsextends.media.player.impl;
import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
public class VideoMediaPlayerUnitTest {
private final PrintStream standardOut = System.out;
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
@BeforeEach
public void setUp() {
System.setOut(new PrintStream(outputStreamCaptor));
}
@AfterEach
public void tearDown() {
System.setOut(standardOut);
}
@Test
public void givenVideoMediaPlayer_whenPlay_thenPrintsPlayingString() {
VideoMediaPlayer videoMediaPlayer = new VideoMediaPlayer();
videoMediaPlayer.play();
Assert.assertEquals("VideoMediaPlayer is Playing", outputStreamCaptor.toString()
.trim());
}
@Test
public void givenVideoMediaPlayer_whenPause_thenPrintsPausedString() {
VideoMediaPlayer videoMediaPlayer = new VideoMediaPlayer();
videoMediaPlayer.pause();
Assert.assertEquals("VideoMediaPlayer is Paused", outputStreamCaptor.toString()
.trim());
}
}

View File

@ -0,0 +1,2 @@
### Relevant Articles:
- [Send a SOAP Object with Feign Client](https://www.baeldung.com/java-feign-send-soap)

View File

@ -4,14 +4,14 @@ This module contains articles about HTTPClient that are part of the HTTPClient E
### Relevant Articles
- [HttpClient 4 Get the Status Code](https://www.baeldung.com/httpclient-status-code)
- [HttpClient with SSL](https://www.baeldung.com/httpclient-ssl)
- [HttpClient Timeout](https://www.baeldung.com/httpclient-timeout)
- [HttpClient 4 Send Custom Cookie](https://www.baeldung.com/httpclient-4-cookies)
- [Custom HTTP Header with the HttpClient](https://www.baeldung.com/httpclient-custom-http-header)
- [HttpClient Basic Authentication](https://www.baeldung.com/httpclient-4-basic-authentication)
- [Posting with HttpClient](https://www.baeldung.com/httpclient-post-http-request)
- [Adding Parameters to HttpClient Requests](https://www.baeldung.com/apache-httpclient-parameters)
- [Apache HttpClient Get the Status Code](https://www.baeldung.com/httpclient-status-code)
- [Apache HttpClient with SSL](https://www.baeldung.com/httpclient-ssl)
- [Apache HttpClient Timeout](https://www.baeldung.com/httpclient-timeout)
- [Apache HttpClient Send Custom Cookie](https://www.baeldung.com/httpclient-cookies)
- [Custom HTTP Header with the Apache HttpClient](https://www.baeldung.com/httpclient-custom-http-header)
- [Apache HttpClient Basic Authentication](https://www.baeldung.com/httpclient-basic-authentication)
- [Posting with Apache HttpClient](https://www.baeldung.com/httpclient-post-http-request)
- [Adding Parameters to Apache HttpClient Requests](https://www.baeldung.com/apache-httpclient-parameters)
### Running the Tests

View File

@ -7,15 +7,14 @@ This module contains articles about HttpClient 4.x
The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles:
- [HttpClient 4 Cancel Request](https://www.baeldung.com/httpclient-cancel-request)
- [HttpClient 4 Cookbook](https://www.baeldung.com/httpclient4)
- [HttpClient 4 Follow Redirects for POST](https://www.baeldung.com/httpclient-redirect-on-http-post)
- [Multipart Upload with HttpClient 4](https://www.baeldung.com/httpclient-multipart-upload)
- [HttpAsyncClient Tutorial](https://www.baeldung.com/httpasyncclient-tutorial)
- [HttpClient 4 Tutorial](https://www.baeldung.com/httpclient-guide)
- [Apache HttpClient Cancel Request](https://www.baeldung.com/httpclient-cancel-request)
- [Apache HttpClient 4 Cookbook](https://www.baeldung.com/httpclient4)
- [Apache HttpClient Follow Redirects for POST](https://www.baeldung.com/httpclient-redirect-on-http-post)
- [Multipart Upload with Apache HttpClient](https://www.baeldung.com/httpclient-multipart-upload)
- [Apache HttpAsyncClient Tutorial](https://www.baeldung.com/httpasyncclient-tutorial)
- [Apache HttpClient Tutorial](https://www.baeldung.com/httpclient-guide)
- [Advanced HttpClient Configuration](https://www.baeldung.com/httpclient-advanced-config)
- [HttpClient 4 Do Not Follow Redirects](https://www.baeldung.com/httpclient-stop-follow-redirect)
- [Custom User-Agent in HttpClient 4](https://www.baeldung.com/httpclient-user-agent-header)
- [Apache HttpClient Do Not Follow Redirects](https://www.baeldung.com/httpclient-stop-follow-redirect)
- [Custom User-Agent in Apache HttpClient](https://www.baeldung.com/httpclient-user-agent-header)
- [Apache HttpClient Connection Management](https://www.baeldung.com/httpclient-connection-management)
- More articles: [[next -->]](../httpclient-2)

View File

@ -1,6 +0,0 @@
## JTA
This module contains articles about the Java Transaction API (JTA).
### Relevant Articles:
- [Guide to Jakarta EE JTA](https://www.baeldung.com/jee-jta)

View File

@ -1,55 +0,0 @@
<?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>jta</artifactId>
<version>1.0-SNAPSHOT</version>
<name>jta</name>
<packaging>jar</packaging>
<description>JEE JTA demo</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-boot-2</relativePath>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-bom</artifactId>
<version>${log4j2.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-bitronix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</dependency>
</dependencies>
<properties>
<spring-boot.version>2.4.7</spring-boot.version>
<log4j2.version>2.17.1</log4j2.version>
</properties>
</project>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="15 seconds" debug="false">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{ISO8601}]-[%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@ -16,4 +16,5 @@ Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-m
- [Introduction to Takes](https://www.baeldung.com/java-takes)
- [Using NullAway to Avoid NullPointerExceptions](https://www.baeldung.com/java-nullaway)
- [Introduction to Alibaba Arthas](https://www.baeldung.com/java-alibaba-arthas-intro)
- More articles [[<-- prev]](/libraries-2) [[next -->]](/libraries-4)
- [Introduction to Structurizr](https://www.baeldung.com/structurizr)
- More articles [[<-- prev]](../libraries-2) [[next -->]](../libraries-4)

View File

@ -86,6 +86,32 @@
<artifactId>error_prone_core</artifactId>
<version>${errorprone.version}</version>
</dependency>
<dependency>
<groupId>com.structurizr</groupId>
<artifactId>structurizr-core</artifactId>
<version>${structurizr.version}</version>
</dependency>
<dependency>
<groupId>com.structurizr</groupId>
<artifactId>structurizr-spring</artifactId>
<version>${structurizr.version}</version>
</dependency>
<dependency>
<groupId>com.structurizr</groupId>
<artifactId>structurizr-client</artifactId>
<version>${structurizr.version}</version>
</dependency>
<dependency>
<groupId>com.structurizr</groupId>
<artifactId>structurizr-analysis</artifactId>
<version>${structurizr.version}</version>
</dependency>
<dependency>
<groupId>com.structurizr</groupId>
<artifactId>structurizr-plantuml</artifactId>
<version>${structurizr.version}</version>
</dependency>
</dependencies>
<repositories>
@ -229,6 +255,7 @@
<nullaway.version>0.3.0</nullaway.version>
<plexus-compiler.version>2.8</plexus-compiler.version>
<errorprone.version>2.1.3</errorprone.version>
<structurizr.version>1.0.0</structurizr.version>
</properties>
</project>

View File

@ -1,10 +1,5 @@
package com.baeldung.structurizr;
import java.io.File;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Set;
import com.structurizr.Workspace;
import com.structurizr.analysis.ComponentFinder;
import com.structurizr.analysis.ReferencedTypesSupportingTypesStrategy;
@ -27,6 +22,11 @@ import com.structurizr.view.SystemContextView;
import com.structurizr.view.View;
import com.structurizr.view.ViewSet;
import java.io.File;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Set;
public class StructurizrSimple {
public static final String PAYMENT_TERMINAL = "Payment Terminal";

View File

@ -9,4 +9,4 @@ This module contains articles about Annotations used in Hibernate.
- [Hibernate One to Many Annotation Tutorial](https://www.baeldung.com/hibernate-one-to-many)
- [Hibernate @WhereJoinTable Annotation](https://www.baeldung.com/hibernate-wherejointable)
- [Usage of the Hibernate @LazyCollection Annotation](https://www.baeldung.com/hibernate-lazycollection)
- [@Immutable in Hibernate](http://www.baeldung.com/hibernate-immutable)
- [@Immutable in Hibernate](https://www.baeldung.com/hibernate-immutable)

View File

@ -4,3 +4,11 @@ This module contains articles about MongoDB in Java.
- [Guide to Upsert in MongoDB](https://www.baeldung.com/mongodb-upsert)
- [Bulk Update of Documents in MongoDB](https://www.baeldung.com/mongodb-bulk-update-documents)
- [Case Insensitive Sorting in MongoDB](https://www.baeldung.com/java-mongodb-case-insensitive-sorting)
- [How to Check Field Existence in MongoDB?](https://www.baeldung.com/mongodb-check-field-exists)
- [Push Operations in MongoDB](https://www.baeldung.com/mongodb-push-operations)
- [Geospatial Support in MongoDB](https://www.baeldung.com/mongodb-geospatial-support)
- [MongoDB Aggregations Using Java](https://www.baeldung.com/java-mongodb-aggregations)
- [Retrieve a Value from MongoDB by Its Key Name](https://www.baeldung.com/mongodb-get-value-by-key-name)
- [Push and Set Operations in Same MongoDB Update](https://www.baeldung.com/java-mongodb-push-set)
- More articles: [[<-- prev]](../java-mongodb)

View File

@ -1,10 +1,5 @@
package com.baeldung.mongo;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.bson.Document;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
@ -13,6 +8,7 @@ import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
import com.mongodb.client.result.UpdateResult;
import org.bson.Document;
public class PushOperations {

View File

@ -0,0 +1,118 @@
package com.baeldung.mongo;
import static com.mongodb.client.model.Aggregates.project;
import static com.mongodb.client.model.Projections.fields;
import java.util.ArrayList;
import java.util.Arrays;
import org.bson.Document;
import org.bson.conversions.Bson;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Projections;
public class RetrieveValue {
private static MongoClient mongoClient;
private static MongoDatabase database;
private static String testCollectionName;
private static String databaseName;
public static void setUp() {
if (mongoClient == null) {
mongoClient = new MongoClient("localhost", 27017);
}
databaseName = "baeldung";
testCollectionName = "travel";
}
public static void retrieveValueUsingFind() {
DB database = mongoClient.getDB(databaseName);
DBCollection collection = database.getCollection(testCollectionName);
BasicDBObject queryFilter = new BasicDBObject();
BasicDBObject projection = new BasicDBObject();
projection.put("passengerId", 1);
projection.put("_id", 0);
DBCursor dbCursor = collection.find(queryFilter, projection);
while (dbCursor.hasNext()) {
System.out.println(dbCursor.next());
}
}
public static void retrieveValueUsingAggregation() {
ArrayList<Document> response = new ArrayList<>();
ArrayList<Bson> pipeline = new ArrayList<>(Arrays.asList(
project(fields(Projections.exclude("_id"), Projections.include("passengerId")))));
database = mongoClient.getDatabase(databaseName);
database.getCollection(testCollectionName)
.aggregate(pipeline)
.allowDiskUse(true)
.into(response);
System.out.println("response:- " + response);
}
public static void retrieveValueAggregationUsingDocument() {
ArrayList<Document> response = new ArrayList<>();
ArrayList<Document> pipeline = new ArrayList<>(Arrays.asList(new Document("$project", new Document("passengerId", 1L))));
database = mongoClient.getDatabase(databaseName);
database.getCollection(testCollectionName)
.aggregate(pipeline)
.allowDiskUse(true)
.into(response);
System.out.println("response:- " + response);
}
public static void main(String args[]) {
//
// Connect to cluster (default is localhost:27017)
//
setUp();
//
// Fetch the data using find query with projected fields
//
retrieveValueUsingFind();
//
// Fetch the data using aggregate pipeline query with projected fields
//
retrieveValueUsingAggregation();
//
// Fetch the data using aggregate pipeline document query with projected fields
//
retrieveValueAggregationUsingDocument();
}
}

View File

@ -1,13 +1,5 @@
package com.baeldung.mongo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import org.bson.Document;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
@ -16,6 +8,13 @@ import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
import com.mongodb.client.result.UpdateResult;
import org.bson.Document;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
public class PushOperationLiveTest {

View File

@ -0,0 +1,114 @@
package com.baeldung.mongo;
import static com.mongodb.client.model.Aggregates.project;
import static com.mongodb.client.model.Projections.fields;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
public class RetrieveValueLiveTest {
private static MongoClient mongoClient;
private static MongoDatabase database;
private static MongoCollection<Document> collection;
private static final String DATASET_JSON = "/travel.json";
private static DB db;
private static DBCollection dbCollection;
@BeforeClass
public static void setup() throws IOException {
if (mongoClient == null) {
mongoClient = new MongoClient("localhost", 27017);
database = mongoClient.getDatabase("baeldung");
db = mongoClient.getDB("baeldung");
dbCollection = db.getCollection("travel");
collection = database.getCollection("travel");
collection.drop();
InputStream is = BulkOperationLiveTest.class.getResourceAsStream(DATASET_JSON);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
reader.lines()
.forEach(line -> collection.insertOne(Document.parse(line)));
reader.close();
}
}
@Test
public void givenTravelCollection_whenfetchUsingFindOperations_thenCheckingForDocument() {
BasicDBObject queryFilter = new BasicDBObject();
BasicDBObject projection = new BasicDBObject();
projection.put("passengerId", 1);
projection.put("_id", 0);
DBCursor dbCursor = dbCollection.find(queryFilter, projection);
while (dbCursor.hasNext()) {
System.out.println(dbCursor.next());
}
Document travelDetail = collection.find(Filters.eq("passengerId", 145))
.first();
assertNotNull(travelDetail);
assertFalse(travelDetail.isEmpty());
}
@Test
public void givenTravelCollection_whenfetchUsingAggregationOperations_thenCheckingForDocument() {
ArrayList<Document> response = new ArrayList<>();
ArrayList<Bson> pipeline = new ArrayList<>(Arrays.asList(project(fields(Projections.exclude("_id"), Projections.include("passengerId")))));
collection.aggregate(pipeline)
.allowDiskUse(true)
.into(response);
Document travelDetail = collection.find(Filters.eq("passengerId", 145))
.first();
assertNotNull(travelDetail);
assertFalse(travelDetail.isEmpty());
}
@Test
public void givenTravelCollection_whenfetchUsingAggregationUsingDocumentOperations_thenCheckingForDocument() {
ArrayList<Document> response = new ArrayList<>();
ArrayList<Document> pipeline = new ArrayList<>(Arrays.asList(new Document("$project", new Document("passengerId", 1L))));
collection.aggregate(pipeline)
.allowDiskUse(true)
.into(response);
Document travelDetail = collection.find(Filters.eq("passengerId", 145))
.first();
assertNotNull(travelDetail);
assertFalse(travelDetail.isEmpty());
}
@AfterClass
public static void cleanUp() {
mongoClient.close();
}
}

View File

@ -1,4 +1,24 @@
package com.baeldung.aggregation;
package com.baeldung.mongo.aggregation;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Accumulators;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
import com.mongodb.client.model.Sorts;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import static com.mongodb.client.model.Aggregates.count;
import static com.mongodb.client.model.Aggregates.group;
@ -11,27 +31,6 @@ import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Accumulators;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
import com.mongodb.client.model.Sorts;
public class AggregationLiveTest {
private static final String DATABASE = "world";

View File

@ -1,4 +1,4 @@
package com.baeldung.existence.field;
package com.baeldung.mongo.existence.field;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
@ -9,7 +9,9 @@ import org.bson.Document;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public class FieldExistenceLiveTest {
private MongoClient mongoClient;

View File

@ -1,16 +1,4 @@
package com.baeldung.geo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bson.Document;
import org.junit.Before;
import org.junit.Test;
package com.baeldung.mongo.geo;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
@ -21,6 +9,17 @@ import com.mongodb.client.model.Indexes;
import com.mongodb.client.model.geojson.Point;
import com.mongodb.client.model.geojson.Polygon;
import com.mongodb.client.model.geojson.Position;
import org.bson.Document;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public class MongoGeospatialLiveTest {

View File

@ -1,7 +1,11 @@
package com.baeldung.ordering.caseinsensitive;
package com.baeldung.mongo.ordering.caseinsensitive;
import com.mongodb.MongoClient;
import com.mongodb.client.*;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Collation;
import com.mongodb.client.model.Projections;
import com.mongodb.client.model.Sorts;

View File

@ -0,0 +1,4 @@
{ "passengerId":145, "passengerName":"Nathan Green", "passengerAge":25, "sourceStation":"London","destinationStation":"Birmingham","seatType":"Slepper","emailAddress":"nathongreen12@gmail.com"}
{ "passengerId":148,"passengerName":"Kevin Joseph","passengerAge":28,"sourceStation":"Manchester","destinationStation":"London","seatType":"Slepper","emailAddress":"kevin13@gmail.com"}
{"passengerId":154,"passengerName":"Sheldon burns","passengerAge":26,"sourceStation":"Cambridge","destinationStation":"Leeds","seatType":"Slepper","emailAddress":"sheldonnn160@gmail.com"}
{"passengerId":168,"passengerName":"Jack Ferguson","passengerAge":24,"sourceStation":"Cardiff","destinationStation":"Coventry","seatType":"Slepper","emailAddress":"jackfergusion9890@gmail.com"}

View File

@ -7,15 +7,11 @@ This module contains articles about MongoDB in Java.
- [A Guide to MongoDB with Java](http://www.baeldung.com/java-mongodb)
- [A Simple Tagging Implementation with MongoDB](http://www.baeldung.com/mongodb-tagging)
- [MongoDB BSON Guide](https://www.baeldung.com/mongodb-bson)
- [Geospatial Support in MongoDB](https://www.baeldung.com/mongodb-geospatial-support)
- [Introduction to Morphia Java ODM for MongoDB](https://www.baeldung.com/mongodb-morphia)
- [MongoDB Aggregations Using Java](https://www.baeldung.com/java-mongodb-aggregations)
- [BSON to JSON Document Conversion in Java](https://www.baeldung.com/java-convert-bson-to-json)
- [How to Check Field Existence in MongoDB?](https://www.baeldung.com/mongodb-check-field-exists)
- [Get Last Inserted Document ID in MongoDB With Java Driver](https://www.baeldung.com/java-mongodb-last-inserted-id)
- [Update Multiple Fields in a MongoDB Document](https://www.baeldung.com/mongodb-update-multiple-fields)
- [Update Documents in MongoDB](https://www.baeldung.com/mongodb-update-documents)
- [Check Collection Existence in MongoDB](https://www.baeldung.com/java-check-collection-existence-mongodb)
- [Case Insensitive Sorting in MongoDB](https://www.baeldung.com/java-mongodb-case-insensitive-sorting)
- [Push and Set Operations in Same MongoDB Update](https://www.baeldung.com/java-mongodb-push-set)
- [Push Operations in MongoDB](https://www.baeldung.com/mongodb-push-operations)
- More articles: [next -->](../java-mongodb-2)

View File

@ -6,6 +6,7 @@
/data
/src/main/webapp/WEB-INF/classes
*/META-INF/*
/transaction-logs
# Packaged files #
*.jar

View File

@ -8,6 +8,7 @@
- [Transactional Annotations: Spring vs. JTA](https://www.baeldung.com/spring-vs-jta-transactional)
- [Test a Mock JNDI Datasource with Spring](https://www.baeldung.com/spring-mock-jndi-datasource)
- [Detecting If a Spring Transaction Is Active](https://www.baeldung.com/spring-transaction-active)
- [Guide to Jakarta EE JTA](https://www.baeldung.com/jee-jta)
### Eclipse Config
After importing the project into Eclipse, you may see the following error:

View File

@ -51,6 +51,21 @@
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
<version>${spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>${spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>${hsqldb.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
@ -79,15 +94,13 @@
</dependencies>
<properties>
<!-- Spring -->
<org.springframework.version>5.2.4.RELEASE</org.springframework.version>
<spring-boot-starter.version>2.3.3.RELEASE</spring-boot-starter.version>
<!-- persistence -->
<org.springframework.version>5.3.18</org.springframework.version>
<spring-boot-starter.version>2.6.6</spring-boot-starter.version>
<persistence-api.version>2.2</persistence-api.version>
<transaction-api.version>1.3</transaction-api.version>
<spring-data-jpa.version>2.2.7.RELEASE</spring-data-jpa.version>
<!-- simple-jndi -->
<simple-jndi.version>0.23.0</simple-jndi.version>
<hsqldb.version>2.5.2</hsqldb.version>
</properties>
</project>

View File

@ -3,7 +3,7 @@ package com.baeldung.jtademo;
import org.hsqldb.jdbc.pool.JDBCXADataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.jta.bitronix.BitronixXADataSourceWrapper;
import org.springframework.boot.jta.atomikos.AtomikosXADataSourceWrapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ -32,7 +32,7 @@ public class JtaDemoApplication {
JDBCXADataSource dataSource = new JDBCXADataSource();
dataSource.setUrl(connectionUrl);
dataSource.setUser("sa");
BitronixXADataSourceWrapper wrapper = new BitronixXADataSourceWrapper();
AtomikosXADataSourceWrapper wrapper = new AtomikosXADataSourceWrapper();
return wrapper.wrapDataSource(dataSource);
}

View File

@ -4,7 +4,6 @@ import com.baeldung.jtademo.dto.TransferLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
@ -24,10 +23,17 @@ public class AuditService {
}
public TransferLog lastTransferLog() {
return jdbcTemplate.query("select FROM_ACCOUNT,TO_ACCOUNT,AMOUNT from AUDIT_LOG order by ID desc", (ResultSetExtractor<TransferLog>) (rs) -> {
if (!rs.next())
return jdbcTemplate.query(
"select FROM_ACCOUNT,TO_ACCOUNT,AMOUNT from AUDIT_LOG order by ID desc",
rs -> {
if (!rs.next()) {
return null;
return new TransferLog(rs.getString(1), rs.getString(2), BigDecimal.valueOf(rs.getDouble(3)));
}
return new TransferLog(
rs.getString(1),
rs.getString(2),
BigDecimal.valueOf(rs.getDouble(3))
);
});
}
}

View File

@ -3,7 +3,6 @@ package com.baeldung.jtademo.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
@ -24,9 +23,12 @@ public class BankAccountService {
}
public BigDecimal balanceOf(String accountId) {
return jdbcTemplate.query("select BALANCE from ACCOUNT where ID=?", new Object[] { accountId }, (ResultSetExtractor<BigDecimal>) (rs) -> {
return jdbcTemplate.query(
"select BALANCE from ACCOUNT where ID=?",
new Object[] { accountId },
rs -> {
rs.next();
return new BigDecimal(rs.getDouble(1));
return BigDecimal.valueOf(rs.getDouble(1));
});
}
}

View File

@ -32,10 +32,10 @@ public class TestHelper {
runScript("audit.sql", jdbcTemplateAudit.getDataSource());
}
private void runScript(String scriptName, DataSource dataSouorce) throws SQLException {
private void runScript(String scriptName, DataSource dataSource) throws SQLException {
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
Resource script = resourceLoader.getResource(scriptName);
try (Connection con = dataSouorce.getConnection()) {
try (Connection con = dataSource.getConnection()) {
ScriptUtils.executeSqlScript(con, script);
}
}

View File

@ -0,0 +1 @@
spring.jta.atomikos.properties.log-base-name=atomikos-log

View File

@ -5,19 +5,19 @@ import com.baeldung.jtademo.services.AuditService;
import com.baeldung.jtademo.services.BankAccountService;
import com.baeldung.jtademo.services.TellerService;
import com.baeldung.jtademo.services.TestHelper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.math.BigDecimal;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@RunWith(SpringRunner.class)
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = JtaDemoApplication.class)
public class JtaDemoUnitTest {
@Autowired
@ -32,31 +32,31 @@ public class JtaDemoUnitTest {
@Autowired
AuditService auditService;
@Before
@BeforeEach
public void beforeTest() throws Exception {
testHelper.runAuditDbInit();
testHelper.runAccountDbInit();
}
@Test
public void givenAnnotationTx_whenNoException_thenAllCommitted() throws Exception {
public void givenAnnotationTx_whenNoException_thenAllCommitted() {
tellerService.executeTransfer("a0000001", "a0000002", BigDecimal.valueOf(500));
assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500));
assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500));
TransferLog lastTransferLog = auditService.lastTransferLog();
assertThat(lastTransferLog).isNotNull();
assertThat(lastTransferLog.getFromAccountId()).isEqualTo("a0000001");
assertThat(lastTransferLog.getToAccountId()).isEqualTo("a0000002");
assertThat(lastTransferLog.getAmount()).isEqualByComparingTo(BigDecimal.valueOf(500));
}
@Test
public void givenAnnotationTx_whenException_thenAllRolledBack() throws Exception {
assertThatThrownBy(() -> {
tellerService.executeTransfer("a0000002", "a0000001", BigDecimal.valueOf(100000));
}).hasMessage("Insufficient fund.");
public void givenAnnotationTx_whenException_thenAllRolledBack() {
assertThatThrownBy(
() -> tellerService.executeTransfer("a0000002", "a0000001", BigDecimal.valueOf(100000))
).hasMessage("Insufficient fund.");
assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000));
assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000));
@ -67,22 +67,21 @@ public class JtaDemoUnitTest {
public void givenProgrammaticTx_whenCommit_thenAllCommitted() throws Exception {
tellerService.executeTransferProgrammaticTx("a0000001", "a0000002", BigDecimal.valueOf(500));
BigDecimal result = accountService.balanceOf("a0000001");
assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500));
assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500));
TransferLog lastTransferLog = auditService.lastTransferLog();
assertThat(lastTransferLog).isNotNull();
assertThat(lastTransferLog.getFromAccountId()).isEqualTo("a0000001");
assertThat(lastTransferLog.getToAccountId()).isEqualTo("a0000002");
assertThat(lastTransferLog.getAmount()).isEqualByComparingTo(BigDecimal.valueOf(500));
}
@Test
public void givenProgrammaticTx_whenRollback_thenAllRolledBack() throws Exception {
assertThatThrownBy(() -> {
tellerService.executeTransferProgrammaticTx("a0000002", "a0000001", BigDecimal.valueOf(100000));
}).hasMessage("Insufficient fund.");
public void givenProgrammaticTx_whenRollback_thenAllRolledBack() {
assertThatThrownBy(
() -> tellerService.executeTransferProgrammaticTx("a0000002", "a0000001", BigDecimal.valueOf(100000))
).hasMessage("Insufficient fund.");
assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000));
assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000));

View File

@ -476,7 +476,6 @@
<module>json-2</module>
<module>json-path</module>
<module>jsoup</module>
<module>jta</module>
<module>kubernetes</module>
<module>ksqldb</module>
<!-- <module>lagom</module> --> <!-- Not a maven project -->
@ -704,7 +703,6 @@
<module>static-analysis</module>
<module>stripe</module>
<module>structurizr</module>
<module>struts-2</module>
<module>tensorflow-java</module>
@ -964,7 +962,6 @@
<module>json-2</module>
<module>json-path</module>
<module>jsoup</module>
<module>jta</module>
<module>ksqldb</module>
@ -1186,7 +1183,6 @@
<module>static-analysis</module>
<module>stripe</module>
<module>structurizr</module>
<module>struts-2</module>
<module>tensorflow-java</module>

View File

@ -0,0 +1,30 @@
package com.baeldung.springboot.swagger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@SpringBootApplication
@EnableSwagger2
public class ArticleApplication {
public static void main(String[] args) {
SpringApplication.run(ArticleApplication.class, args);
}
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}

View File

@ -0,0 +1,28 @@
package com.baeldung.springboot.swagger.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.baeldung.springboot.swagger.model.Article;
import com.baeldung.springboot.swagger.service.ArticleService;
@RestController
@RequestMapping("/articles")
public class ArticlesController {
@Autowired
private ArticleService articleService;
@GetMapping("")
public List<Article> getAllArticles() {
return articleService.getAllArticles();
}
@PostMapping("")
public void addArticle(@RequestBody Article article) {
articleService.addArticle(article);
}
}

View File

@ -0,0 +1,54 @@
package com.baeldung.springboot.swagger.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiParam;
public class Article {
//@JsonIgnore
//@JsonProperty(access = JsonProperty.Access.READ_ONLY)
//@ApiModelProperty(hidden = true)
//@ApiParam(hidden = true)
//@ApiModelProperty(readOnly = true)
private int id;
private String title;
private int numOfWords;
public Article() {
}
public Article(int id, String title) {
this.id = id;
this.title = title;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getNumOfWords() {
return numOfWords;
}
public void setNumOfWords(int numOfWords) {
this.numOfWords = numOfWords;
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.springboot.swagger.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.baeldung.springboot.swagger.model.Article;
@Service
public class ArticleService {
private List<Article> articles = new ArrayList<>();
public List<Article> getAllArticles() {
return articles;
}
public void addArticle(Article article) {
article.setId(articles.size() + 1);
articles.add(article);
}
}

View File

@ -46,7 +46,7 @@
<module>spring-cloud-circuit-breaker</module>
<module>spring-cloud-eureka-self-preservation</module>
<!-- <module>spring-cloud-openfeign</module> --> <!-- Fixing under JAVA-10446 -->
<!-- <module>spring-cloud-netflix-feign</module> --> <!-- Fixing under JAVA-10431 -->
<module>spring-cloud-netflix-feign</module>
<module>spring-cloud-sentinel</module>
<module>spring-cloud-dapr</module>
<module>spring-cloud-docker</module>

View File

@ -51,13 +51,16 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-wiremock</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<spring-cloud.version>Camden.SR7</spring-cloud.version>
<feign-ok.version>8.18.0</feign-ok.version>
<!-- <spring-cloud.version>Hoxton.SR8</spring-cloud.version> -->
<!-- <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> -->
</properties>
</project>

View File

@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
@FeignClient(value = "jplaceholder",
url = "https://jsonplaceholder.typicode.com/",
url = "${external.api.url}",
configuration = ClientConfiguration.class,
fallback = JSONPlaceHolderFallback.class)
public interface JSONPlaceHolderClient {
@ -19,7 +19,7 @@ public interface JSONPlaceHolderClient {
@RequestMapping(method = RequestMethod.GET, value = "/posts")
List<Post> getPosts();
@RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json")
Post getPostById(@PathVariable("postId") Long postId);
}

View File

@ -1,3 +1,5 @@
spring.application.name=netflix-feign
logging.level.com.baeldung.cloud.netflix.feign.client=DEBUG
feign.hystrix.enabled=true
external.api.url=https://jsonplaceholder.typicode.com/

View File

@ -1,21 +0,0 @@
package com.baeldung.cloud.netflix.feign;
import com.baeldung.cloud.netflix.feign.config.ClientConfiguration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
@EnableAutoConfiguration
@ContextConfiguration(classes = { ClientConfiguration.class })
public class ExampleTestApplication {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}

View File

@ -2,42 +2,97 @@ package com.baeldung.cloud.netflix.feign;
import com.baeldung.cloud.netflix.feign.model.Post;
import com.baeldung.cloud.netflix.feign.service.JSONPlaceHolderService;
import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.verification.LoggedRequest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
import static org.junit.Assert.assertFalse;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.exactly;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@RunWith(SpringRunner.class)
@SpringBootTest
@SpringBootTest(properties = {"external.api.url=http://localhost:${wiremock.server.port}"})
@AutoConfigureWireMock(port = 0)
public class NetflixFeignUnitTest {
@Autowired
private JSONPlaceHolderService jsonPlaceHolderService;
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
@Before
public void setup() {
WireMock.reset();
}
@Test
public void whenGetPosts_thenListPostSizeGreaterThanZero() {
public void givenExternalApiAvailable_whenGetPosts_thenPostsReturned() {
WireMock.stubFor(get(urlEqualTo("/posts"))
.willReturn(okJson("[{ \"userId\": 1, \"id\": 1, \"title\": \"post 1 title\", \"body\": \"post 1 body\" }, "
+ "{ \"userId\": 1, \"id\": 2, \"title\": \"post 2 title\", \"body\": \"post 2 body\" }]")));
List<Post> posts = jsonPlaceHolderService.getPosts();
assertFalse(posts.isEmpty());
assertEquals(2, posts.size());
verify(exactly(1), getRequestedFor(urlEqualTo("/posts")));
}
@Test
public void whenGetPostWithId_thenPostExist() {
public void givenExternalApiUnavailable_whenGetPosts_thenEmpty() {
WireMock.stubFor(get(urlEqualTo("/posts"))
.willReturn(aResponse().withStatus(500)));
List<Post> posts = jsonPlaceHolderService.getPosts();
assertTrue(posts.isEmpty());
verify(exactly(1), getRequestedFor(urlEqualTo("/posts")));
}
@Test
public void givenExternalApiAvailable_whenGetPostWithId_thenPostExists() {
WireMock.stubFor(get(urlEqualTo("/posts/1"))
.willReturn(okJson("{ \"userId\": 1, \"id\": 1, \"title\": \"post 1 title\", \"body\": \"post 1 body\" }")));
Post post = jsonPlaceHolderService.getPostById(1L);
assertNotNull(post);
verify(exactly(1), getRequestedFor(urlEqualTo("/posts/1")));
}
@Test
public void givenExternalApiUnavailable_whenGetPostWithId_thenNull() {
WireMock.stubFor(get(urlEqualTo("/posts/1"))
.willReturn(aResponse().withStatus(500)));
Post post = jsonPlaceHolderService.getPostById(1L);
assertNull(post);
verify(exactly(1), getRequestedFor(urlEqualTo("/posts/1")));
}
private static ResponseDefinitionBuilder okJson(String json) {
return aResponse()
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.withBody(json);
}
}

View File

@ -4,11 +4,11 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Processor;
import org.springframework.cloud.stream.schema.client.EnableSchemaRegistryClient;
@SpringBootApplication
@EnableBinding(Processor.class)
@EnableSchemaRegistryClient
// The @EnableSchemaRegistryClient annotation needs to be uncommented to use the Spring native method.
// @EnableSchemaRegistryClient
public class AvroKafkaApplication {
public static void main(String[] args) {

View File

@ -1,4 +1,4 @@
package com.baeldung.reactive.debugging.consumer.chronjobs;
package com.baeldung.reactive.debugging.consumer.cronjobs;
import com.baeldung.reactive.debugging.consumer.model.Foo;
import com.baeldung.reactive.debugging.consumer.model.FooDto;
@ -16,10 +16,10 @@ import java.time.Duration;
import java.util.concurrent.ThreadLocalRandom;
@Component
public class ChronJobs {
public class CronJobs {
private static Logger logger = LoggerFactory.getLogger(ChronJobs.class);
private WebClient client = WebClient.create("http://localhost:8081");
final Logger logger = LoggerFactory.getLogger(CronJobs.class);
final WebClient client = WebClient.create("http://localhost:8081");
@Autowired
private FooService service;
@ -36,8 +36,10 @@ public class ChronJobs {
logger.debug("process 1 with dto id {} name{}", dto.getId(), dto.getName());
return new Foo(dto);
});
Integer random = ThreadLocalRandom.current()
int random = ThreadLocalRandom.current()
.nextInt(0, 3);
switch (random) {
case 0:
logger.info("process 1 with approach 1");
@ -51,7 +53,6 @@ public class ChronJobs {
logger.info("process 1 with approach 2");
service.processFooInAnotherScenario(fluxFoo);
break;
}
}
@ -67,8 +68,10 @@ public class ChronJobs {
logger.debug("process 2 with dto id {} name{}", dto.getId(), dto.getName());
return new Foo(dto);
});
Integer random = ThreadLocalRandom.current()
int random = ThreadLocalRandom.current()
.nextInt(0, 3);
switch (random) {
case 0:
logger.info("process 2 with approach 1");
@ -82,7 +85,6 @@ public class ChronJobs {
logger.info("process 2 with approach 2");
service.processFooInAnotherScenario(fluxFoo);
break;
}
}

View File

@ -1,14 +1,12 @@
package com.baeldung.reactive.debugging.consumer.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.concurrent.ThreadLocalRandom;
@Getter
@Setter
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Foo {
@ -18,10 +16,16 @@ public class Foo {
private Integer quantity;
public Foo(FooDto dto) {
this.id = (ThreadLocalRandom.current()
.nextInt(0, 100) == 0) ? null : dto.getId();
this.id = randomId() == 0 ? null : dto.getId();
this.formattedName = dto.getName();
this.quantity = ThreadLocalRandom.current()
.nextInt(0, 10);
this.quantity = randomQuantity();
}
private static int randomId() {
return ThreadLocalRandom.current().nextInt(0, 100);
}
private static int randomQuantity() {
return ThreadLocalRandom.current().nextInt(0, 10);
}
}

View File

@ -1,16 +1,15 @@
package com.baeldung.reactive.debugging.consumer.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FooDto {
private Integer id;
private String name;
}

View File

@ -1,44 +1,40 @@
package com.baeldung.reactive.debugging.consumer.service;
import com.baeldung.reactive.debugging.consumer.model.Foo;
import reactor.core.publisher.Flux;
import java.util.concurrent.ThreadLocalRandom;
public class FooNameHelper {
public static Flux<Foo> concatAndSubstringFooName(Flux<Foo> flux) {
flux = concatFooName(flux);
flux = substringFooName(flux);
return flux;
public static Foo concatAndSubstringFooName(Foo foo) {
Foo concat = concatFooName(foo);
return substringFooName(concat);
}
public static Flux<Foo> concatFooName(Flux<Foo> flux) {
flux = flux.map(foo -> {
String processedName = null;
Integer random = ThreadLocalRandom.current()
public static Foo concatFooName(Foo foo) {
int random = ThreadLocalRandom.current()
.nextInt(0, 80);
processedName = (random != 0) ? foo.getFormattedName() : foo.getFormattedName() + "-bael";
String processedName = (random != 0)
? foo.getFormattedName()
: foo.getFormattedName() + "-bael";
foo.setFormattedName(processedName);
return foo;
});
return flux;
}
public static Flux<Foo> substringFooName(Flux<Foo> flux) {
return flux.map(foo -> {
String processedName;
Integer random = ThreadLocalRandom.current()
public static Foo substringFooName(Foo foo) {
int random = ThreadLocalRandom.current()
.nextInt(0, 100);
processedName = (random == 0) ? foo.getFormattedName()
.substring(10, 15)
: foo.getFormattedName()
.substring(0, 5);
String processedName = (random == 0)
? foo.getFormattedName().substring(10, 15)
: foo.getFormattedName().substring(0, 5);
foo.setFormattedName(processedName);
return foo;
});
}
}

View File

@ -1,30 +1,24 @@
package com.baeldung.reactive.debugging.consumer.service;
import com.baeldung.reactive.debugging.consumer.model.Foo;
import reactor.core.publisher.Flux;
import java.util.concurrent.ThreadLocalRandom;
public class FooQuantityHelper {
public static Flux<Foo> processFooReducingQuantity(Flux<Foo> flux) {
flux = flux.map(foo -> {
Integer result;
Integer random = ThreadLocalRandom.current()
.nextInt(0, 90);
result = (random == 0) ? result = 0 : foo.getQuantity() + 2;
public static Foo processFooReducingQuantity(Foo foo) {
int random = ThreadLocalRandom.current().nextInt(0, 90);
int result = (random == 0) ? 0 : foo.getQuantity() + 2;
foo.setQuantity(result);
return foo;
});
return divideFooQuantity(flux);
return divideFooQuantity(foo);
}
public static Flux<Foo> divideFooQuantity(Flux<Foo> flux) {
return flux.map(foo -> {
Integer result = Math.round(5 / foo.getQuantity());
public static Foo divideFooQuantity(Foo foo) {
Integer result = (int) Math.round(5.0 / foo.getQuantity());
foo.setQuantity(result);
return foo;
});
}
}

View File

@ -3,22 +3,22 @@ package com.baeldung.reactive.debugging.consumer.service;
import com.baeldung.reactive.debugging.consumer.model.Foo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
public class FooReporter {
private static Logger logger = LoggerFactory.getLogger(FooReporter.class);
private static final Logger LOGGER = LoggerFactory.getLogger(FooReporter.class);
public static Flux<Foo> reportResult(Flux<Foo> input, String approach) {
return input.map(foo -> {
if (foo.getId() == null)
public static Foo reportResult(Foo foo, String approach) {
if (foo.getId() == null) {
throw new IllegalArgumentException("Null id is not valid!");
logger.info("Reporting for approach {}: Foo with id '{}' name '{}' and quantity '{}'", approach, foo.getId(), foo.getFormattedName(), foo.getQuantity());
}
LOGGER.info("Reporting for approach {}: Foo with id '{}' name '{}' and quantity '{}'",
approach, foo.getId(), foo.getFormattedName(), foo.getQuantity());
return foo;
});
}
public static Flux<Foo> reportResult(Flux<Foo> input) {
public static Foo reportResult(Foo input) {
return reportResult(input, "default");
}
}

View File

@ -7,112 +7,107 @@ import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;
import static com.baeldung.reactive.debugging.consumer.service.FooNameHelper.concatAndSubstringFooName;
import static com.baeldung.reactive.debugging.consumer.service.FooNameHelper.substringFooName;
import static com.baeldung.reactive.debugging.consumer.service.FooQuantityHelper.divideFooQuantity;
import static com.baeldung.reactive.debugging.consumer.service.FooQuantityHelper.processFooReducingQuantity;
import static com.baeldung.reactive.debugging.consumer.service.FooReporter.reportResult;
@Component
public class FooService {
private static Logger logger = LoggerFactory.getLogger(FooService.class);
private static final Logger LOGGER = LoggerFactory.getLogger(FooService.class);
public void processFoo(Flux<Foo> flux) {
flux = FooNameHelper.concatFooName(flux);
flux = FooNameHelper.substringFooName(flux);
flux = flux.log();
flux = FooReporter.reportResult(flux);
flux = flux.doOnError(error -> {
logger.error("The following error happened on processFoo method!", error);
});
flux.subscribe();
flux.map(FooNameHelper::concatFooName)
.map(FooNameHelper::substringFooName)
.log()
.map(FooReporter::reportResult)
.doOnError(error -> LOGGER.error("The following error happened on processFoo method!", error))
.subscribe();
}
public void processFooInAnotherScenario(Flux<Foo> flux) {
flux = FooNameHelper.substringFooName(flux);
flux = FooQuantityHelper.divideFooQuantity(flux);
flux.subscribe();
flux.map(FooNameHelper::substringFooName)
.map(FooQuantityHelper::divideFooQuantity)
.subscribe();
}
public void processUsingApproachOneWithErrorHandling(Flux<Foo> flux) {
logger.info("starting approach one w error handling!");
flux = concatAndSubstringFooName(flux);
flux = concatAndSubstringFooName(flux);
flux = substringFooName(flux);
flux = processFooReducingQuantity(flux);
flux = processFooReducingQuantity(flux);
flux = processFooReducingQuantity(flux);
flux = reportResult(flux, "ONE w/ EH");
flux = flux.doOnError(error -> {
logger.error("Approach 1 with Error Handling failed!", error);
});
flux.subscribe();
LOGGER.info("starting approach one w error handling!");
flux.map(FooNameHelper::concatAndSubstringFooName)
.map(FooNameHelper::concatAndSubstringFooName)
.map(FooNameHelper::substringFooName)
.map(FooQuantityHelper::processFooReducingQuantity)
.map(FooQuantityHelper::processFooReducingQuantity)
.map(FooQuantityHelper::processFooReducingQuantity)
.map(FooReporter::reportResult)
.doOnError(error -> LOGGER.error("Approach 1 with Error Handling failed!", error))
.subscribe();
}
public void processUsingApproachThree(Flux<Foo> flux) {
logger.info("starting approach three!");
flux = concatAndSubstringFooName(flux);
flux = reportResult(flux, "THREE");
flux = flux.doOnError(error -> {
logger.error("Approach 3 failed!", error);
});
flux.subscribe();
LOGGER.info("starting approach three!");
flux.map(FooNameHelper::concatAndSubstringFooName)
.map(foo -> reportResult(foo, "THREE"))
.doOnError(error -> LOGGER.error("Approach 3 failed!", error))
.subscribe();
}
public void processUsingApproachFourWithCheckpoint(Flux<Foo> flux) {
logger.info("starting approach four!");
flux = concatAndSubstringFooName(flux);
flux = flux.checkpoint("CHECKPOINT 1");
flux = concatAndSubstringFooName(flux);
flux = divideFooQuantity(flux);
flux = flux.checkpoint("CHECKPOINT 2", true);
flux = reportResult(flux, "FOUR");
flux = concatAndSubstringFooName(flux).doOnError(error -> {
logger.error("Approach 4 failed!", error);
});
flux.subscribe();
LOGGER.info("starting approach four!");
flux.map(FooNameHelper::concatAndSubstringFooName)
.checkpoint("CHECKPOINT 1")
.map(FooNameHelper::concatAndSubstringFooName)
.map(FooQuantityHelper::divideFooQuantity)
.checkpoint("CHECKPOINT 2", true)
.map(foo -> reportResult(foo, "FOUR"))
.map(FooNameHelper::concatAndSubstringFooName)
.doOnError(error -> LOGGER.error("Approach 4 failed!", error))
.subscribe();
}
public void processUsingApproachFourWithInitialCheckpoint(Flux<Foo> flux) {
logger.info("starting approach four!");
flux = concatAndSubstringFooName(flux);
flux = flux.checkpoint("CHECKPOINT 1", true);
flux = concatAndSubstringFooName(flux);
flux = divideFooQuantity(flux);
flux = reportResult(flux, "FOUR");
flux = flux.doOnError(error -> {
logger.error("Approach 4-2 failed!", error);
});
flux.subscribe();
LOGGER.info("starting approach four!");
flux.map(FooNameHelper::concatAndSubstringFooName)
.checkpoint("CHECKPOINT 1", true)
.map(FooNameHelper::concatAndSubstringFooName)
.map(FooQuantityHelper::divideFooQuantity)
.map(foo -> reportResult(foo, "FOUR"))
.map(FooNameHelper::concatAndSubstringFooName)
.doOnError(error -> LOGGER.error("Approach 4-2 failed!", error))
.subscribe();
}
public void processUsingApproachFivePublishingToDifferentParallelThreads(Flux<Foo> flux) {
logger.info("starting approach five-parallel!");
flux = concatAndSubstringFooName(flux).publishOn(Schedulers.newParallel("five-parallel-foo"))
.log();
flux = concatAndSubstringFooName(flux);
flux = divideFooQuantity(flux);
flux = reportResult(flux, "FIVE-PARALLEL").publishOn(Schedulers.newSingle("five-parallel-bar"));
flux = concatAndSubstringFooName(flux).doOnError(error -> {
logger.error("Approach 5-parallel failed!", error);
});
flux.subscribeOn(Schedulers.newParallel("five-parallel-starter"))
LOGGER.info("starting approach five-parallel!");
flux.map(FooNameHelper::concatAndSubstringFooName)
.publishOn(Schedulers.newParallel("five-parallel-foo"))
.log()
.map(FooNameHelper::concatAndSubstringFooName)
.map(foo -> reportResult(foo, "FIVE-PARALLEL"))
.publishOn(Schedulers.newSingle("five-parallel-bar"))
.map(FooNameHelper::concatAndSubstringFooName)
.doOnError(error -> LOGGER.error("Approach 5-parallel failed!", error))
.subscribeOn(Schedulers.newParallel("five-parallel-starter"))
.subscribe();
}
public void processUsingApproachFivePublishingToDifferentSingleThreads(Flux<Foo> flux) {
logger.info("starting approach five-single!");
flux = flux.log()
.subscribeOn(Schedulers.newSingle("five-single-starter"));
flux = concatAndSubstringFooName(flux).publishOn(Schedulers.newSingle("five-single-foo"));
flux = concatAndSubstringFooName(flux);
flux = divideFooQuantity(flux);
flux = reportResult(flux, "FIVE-SINGLE").publishOn(Schedulers.newSingle("five-single-bar"));
flux = concatAndSubstringFooName(flux).doOnError(error -> {
logger.error("Approach 5-single failed!", error);
});
flux.subscribe();
LOGGER.info("starting approach five-single!");
flux.log()
.subscribeOn(Schedulers.newSingle("five-single-starter"))
.map(FooNameHelper::concatAndSubstringFooName)
.publishOn(Schedulers.newSingle("five-single-foo"))
.map(FooNameHelper::concatAndSubstringFooName)
.map(FooQuantityHelper::divideFooQuantity)
.map(foo -> reportResult(foo, "FIVE-SINGLE"))
.publishOn(Schedulers.newSingle("five-single-bar"))
.map(FooNameHelper::concatAndSubstringFooName)
.doOnError(error -> LOGGER.error("Approach 5-single failed!", error))
.subscribe();
}
}

View File

@ -16,30 +16,31 @@ import java.util.concurrent.ThreadLocalRandom;
@Component
public class ServerHandler {
private static Logger logger = LoggerFactory.getLogger(ServerHandler.class);
private static final Logger LOGGER = LoggerFactory.getLogger(ServerHandler.class);
public Mono<ServerResponse> useHandler(final ServerRequest request) {
// there are chances that something goes wrong here...
return ServerResponse.ok()
.contentType(MediaType.TEXT_EVENT_STREAM)
.body(Flux.interval(Duration.ofSeconds(1))
.map(sequence -> {
logger.info("retrieving Foo. Sequence: {}", sequence);
if (ThreadLocalRandom.current()
.nextInt(0, 50) == 1) {
throw new RuntimeException("There was an error retrieving the Foo!");
}
return new Foo(sequence, "name" + sequence);
}), Foo.class);
.body(getFlux(), Foo.class);
}
public Mono<ServerResponse> useHandlerFinite(final ServerRequest request) {
return ServerResponse.ok()
.contentType(MediaType.TEXT_EVENT_STREAM)
.body(Flux.range(0, 50)
.map(sequence -> new Foo(new Long(sequence), "theFooNameNumber" + sequence)
), Foo.class);
}
private static Flux<Foo> getFlux() {
return Flux.interval(Duration.ofSeconds(1))
.map(sequence -> {
return new Foo(new Long(sequence), "theFooNameNumber" + sequence);
}), Foo.class);
LOGGER.info("retrieving Foo. Sequence: {}", sequence);
if (ThreadLocalRandom.current().nextInt(0, 50) == 1) {
throw new RuntimeException("There was an error retrieving the Foo!");
}
return new Foo(sequence, "name" + sequence);
});
}
}

View File

@ -45,15 +45,15 @@ public class ConsumerFooServiceIntegrationTest {
Collection<String> allSuppressedEntries = ListAppender.getEvents()
.stream()
.map(ILoggingEvent::getThrowableProxy)
.flatMap(t -> {
return Optional.ofNullable(t)
.flatMap(t -> Optional.ofNullable(t)
.map(IThrowableProxy::getSuppressed)
.map(Arrays::stream)
.orElse(Stream.empty());
})
.orElse(Stream.empty()))
.map(IThrowableProxy::getClassName)
.collect(Collectors.toList());
assertThat(allLoggedEntries).anyMatch(entry -> entry.contains("The following error happened on processFoo method!"))
assertThat(allLoggedEntries)
.anyMatch(entry -> entry.contains("The following error happened on processFoo method!"))
.anyMatch(entry -> entry.contains("| onSubscribe"))
.anyMatch(entry -> entry.contains("| cancel()"));

View File

@ -1,6 +1,5 @@
package com.baeldung.reactive.debugging.consumer;
import com.baeldung.reactive.debugging.consumer.service.FooService;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.test.web.reactive.server.WebTestClient;
@ -13,8 +12,6 @@ import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec;
*/
public class ConsumerFooServiceLiveTest {
FooService service = new FooService();
private static final String BASE_URL = "http://localhost:8082";
private static final String DEBUG_HOOK_ON = BASE_URL + "/debug-hook-on";
private static final String DEBUG_HOOK_OFF = BASE_URL + "/debug-hook-off";

View File

@ -8,18 +8,18 @@ import java.util.List;
public class ListAppender extends AppenderBase<ILoggingEvent> {
static private List<ILoggingEvent> events = new ArrayList<>();
private static final List<ILoggingEvent> EVENTS = new ArrayList<>();
@Override
protected void append(ILoggingEvent eventObject) {
events.add(eventObject);
EVENTS.add(eventObject);
}
public static List<ILoggingEvent> getEvents() {
return events;
return EVENTS;
}
public static void clearEventList() {
events.clear();
EVENTS.clear();
}
}

View File

@ -5,6 +5,7 @@ This module contains articles about OpenID with Spring Security
### Relevant articles
- [Spring Security and OpenID Connect](https://www.baeldung.com/spring-security-openid-connect)
- [Spring Security Map Authorities from JWT](https://www.baeldung.com/spring-security-map-authorities-jwt)
### OpenID Connect with Spring Security

View File

@ -1,6 +0,0 @@
## Structurizr
This module contains articles about Structurizr
### Relevant Articles:
- [Intro to Structurizr](https://www.baeldung.com/structurizr)

View File

@ -1,49 +0,0 @@
<?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>structurizr</artifactId>
<name>structurizr</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.structurizr</groupId>
<artifactId>structurizr-core</artifactId>
<version>${structurizr.version}</version>
</dependency>
<dependency>
<groupId>com.structurizr</groupId>
<artifactId>structurizr-spring</artifactId>
<version>${structurizr.version}</version>
</dependency>
<dependency>
<groupId>com.structurizr</groupId>
<artifactId>structurizr-client</artifactId>
<version>${structurizr.version}</version>
</dependency>
<dependency>
<groupId>com.structurizr</groupId>
<artifactId>structurizr-analysis</artifactId>
<version>${structurizr.version}</version>
</dependency>
<dependency>
<groupId>com.structurizr</groupId>
<artifactId>structurizr-plantuml</artifactId>
<version>${structurizr.version}</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<structurizr.version>1.0.0</structurizr.version>
</properties>
</project>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@ -83,7 +83,7 @@ public class RestAssuredAdvancedLiveTest {
@Test
public void whenUseMultipleHeaders_thenOK(){
given().header("User-Agent", "MyAppName","Accept-Charset","utf-8").when().get("/users/eugenp").then().statusCode(200);
given().headers("User-Agent", "MyAppName","Accept-Charset","utf-8").when().get("/users/eugenp").then().statusCode(200);
}
//======= cookie