Merge branch 'master' into JAVA-11196-split-httpclient-module
This commit is contained in:
commit
db29759c69
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 + '\'' +
|
||||
"} ";
|
||||
}
|
||||
}
|
|
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -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 + '\'' +
|
||||
"} ";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.baeldung.implementsvsextends.media.player;
|
||||
|
||||
public interface AdvancedPlayerOptions {
|
||||
|
||||
void seek();
|
||||
|
||||
void fastForward();
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.baeldung.implementsvsextends.media.player;
|
||||
|
||||
public interface MediaPlayer {
|
||||
|
||||
void play();
|
||||
|
||||
void pause();
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
### Relevant Articles:
|
||||
- [Send a SOAP Object with Feign Client](https://www.baeldung.com/java-feign-send-soap)
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
55
jta/pom.xml
55
jta/pom.xml
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
|
@ -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";
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
@ -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();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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";
|
|
@ -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;
|
|
@ -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 {
|
||||
|
|
@ -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;
|
|
@ -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"}
|
|
@ -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)
|
|
@ -6,6 +6,7 @@
|
|||
/data
|
||||
/src/main/webapp/WEB-INF/classes
|
||||
*/META-INF/*
|
||||
/transaction-logs
|
||||
|
||||
# Packaged files #
|
||||
*.jar
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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))
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
spring.jta.atomikos.properties.log-base-name=atomikos-log
|
|
@ -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));
|
4
pom.xml
4
pom.xml
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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/
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()"));
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
## Structurizr
|
||||
|
||||
This module contains articles about Structurizr
|
||||
|
||||
### Relevant Articles:
|
||||
- [Intro to Structurizr](https://www.baeldung.com/structurizr)
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue