diff --git a/core-java-modules/core-java-20/README.md b/core-java-modules/core-java-20/README.md
new file mode 100644
index 0000000000..7e20469e44
--- /dev/null
+++ b/core-java-modules/core-java-20/README.md
@@ -0,0 +1,2 @@
+## Relevant Articles
+- TBD
\ No newline at end of file
diff --git a/core-java-modules/core-java-20/pom.xml b/core-java-modules/core-java-20/pom.xml
new file mode 100644
index 0000000000..9562a41b1c
--- /dev/null
+++ b/core-java-modules/core-java-20/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+ com.baeldung.core-java-modules
+ core-java-modules
+ 0.0.1-SNAPSHOT
+
+
+ core-java-20
+
+
+ 20
+ 20
+ UTF-8
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 20
+
+ --enable-preview
+ --add-modules=jdk.incubator.concurrent
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ --enable-preview --add-modules=jdk.incubator.concurrent
+
+
+
+
+
+
+
+ jakarta.servlet
+ jakarta.servlet-api
+ 6.0.0
+ provided
+
+
+ org.assertj
+ assertj-core
+ 3.24.2
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ 5.2.0
+ test
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/classic/Controller.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/classic/Controller.java
new file mode 100644
index 0000000000..92edc57e48
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/classic/Controller.java
@@ -0,0 +1,33 @@
+package com.baeldung.scopedvalues.classic;
+
+import com.baeldung.scopedvalues.data.Data;
+import com.baeldung.scopedvalues.data.User;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Optional;
+
+public class Controller {
+
+ private final Service service = new Service();
+
+ public void processRequest(HttpServletRequest request, HttpServletResponse response, User loggedInUser) {
+ Optional data = service.getData(request, loggedInUser);
+ if (data.isPresent()) {
+ try {
+ PrintWriter out = response.getWriter();
+ response.setContentType("application/json");
+ out.print(data.get());
+ out.flush();
+ response.setStatus(200);
+ } catch (IOException e) {
+ response.setStatus(500);
+ }
+ } else {
+ response.setStatus(400);
+ }
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/classic/Repository.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/classic/Repository.java
new file mode 100644
index 0000000000..3085b3be58
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/classic/Repository.java
@@ -0,0 +1,16 @@
+package com.baeldung.scopedvalues.classic;
+
+import com.baeldung.scopedvalues.data.Data;
+import com.baeldung.scopedvalues.data.User;
+
+import java.util.Optional;
+
+public class Repository {
+
+ public Optional getData(String id, User user) {
+ return user.isAdmin()
+ ? Optional.of(new Data(id, "Title 1", "Description 1"))
+ : Optional.empty();
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/classic/Server.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/classic/Server.java
new file mode 100644
index 0000000000..71afa9e675
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/classic/Server.java
@@ -0,0 +1,42 @@
+package com.baeldung.scopedvalues.classic;
+
+import com.baeldung.scopedvalues.data.User;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.*;
+
+public class Server {
+
+ private static final List AUTHENTICATED_USERS = List.of(
+ new User("1", "admin", "123456", true),
+ new User("2", "user", "123456", false)
+ );
+ private final Controller controller = new Controller();
+ private final ExecutorService executor = Executors.newFixedThreadPool(5);
+
+ public void serve(HttpServletRequest request, HttpServletResponse response) throws InterruptedException, ExecutionException {
+ Optional user = authenticateUser(request);
+ if (user.isPresent()) {
+ Future> future = executor.submit(() ->
+ controller.processRequest(request, response, user.get()));
+ future.get();
+ } else {
+ response.setStatus(401);
+ }
+ }
+
+ private Optional authenticateUser(HttpServletRequest request) {
+ return AUTHENTICATED_USERS.stream()
+ .filter(user -> checkUserPassword(user, request))
+ .findFirst();
+ }
+
+ private boolean checkUserPassword(User user, HttpServletRequest request) {
+ return user.name().equals(request.getParameter("user_name"))
+ && user.password().equals(request.getParameter("user_pw"));
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/classic/Service.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/classic/Service.java
new file mode 100644
index 0000000000..011f793001
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/classic/Service.java
@@ -0,0 +1,18 @@
+package com.baeldung.scopedvalues.classic;
+
+import com.baeldung.scopedvalues.data.Data;
+import com.baeldung.scopedvalues.data.User;
+import jakarta.servlet.http.HttpServletRequest;
+
+import java.util.Optional;
+
+public class Service {
+
+ private final Repository repository = new Repository();
+
+ public Optional getData(HttpServletRequest request, User loggedInUser) {
+ String id = request.getParameter("data_id");
+ return repository.getData(id, loggedInUser);
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/data/Data.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/data/Data.java
new file mode 100644
index 0000000000..70be41c1ac
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/data/Data.java
@@ -0,0 +1,3 @@
+package com.baeldung.scopedvalues.data;
+
+public record Data(String id, String title, String description) {}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/data/User.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/data/User.java
new file mode 100644
index 0000000000..22e0a4243f
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/data/User.java
@@ -0,0 +1,3 @@
+package com.baeldung.scopedvalues.data;
+
+public record User(String id, String name, String password, boolean isAdmin) {}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/Controller.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/Controller.java
new file mode 100644
index 0000000000..239ee88f19
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/Controller.java
@@ -0,0 +1,37 @@
+package com.baeldung.scopedvalues.scoped;
+
+import com.baeldung.scopedvalues.data.Data;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jdk.incubator.concurrent.ScopedValue;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Optional;
+
+public class Controller {
+
+ private final Service internalService = new Service();
+
+ public void processRequest(HttpServletRequest request, HttpServletResponse response) {
+ Optional data = internalService.getData(request);
+
+ ScopedValue.where(Server.LOGGED_IN_USER, null)
+ .run(internalService::extractData);
+
+ if (data.isPresent()) {
+ try {
+ PrintWriter out = response.getWriter();
+ response.setContentType("application/json");
+ out.print(data.get());
+ out.flush();
+ response.setStatus(200);
+ } catch (IOException e) {
+ response.setStatus(500);
+ }
+ } else {
+ response.setStatus(400);
+ }
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/Repository.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/Repository.java
new file mode 100644
index 0000000000..a40191eb3c
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/Repository.java
@@ -0,0 +1,17 @@
+package com.baeldung.scopedvalues.scoped;
+
+import com.baeldung.scopedvalues.data.Data;
+import com.baeldung.scopedvalues.data.User;
+
+import java.util.Optional;
+
+public class Repository {
+
+ public Optional getData(String id) {
+ User loggedInUser = Server.LOGGED_IN_USER.get();
+ return loggedInUser.isAdmin()
+ ? Optional.of(new Data(id, "Title 1", "Description 1"))
+ : Optional.empty();
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/Server.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/Server.java
new file mode 100644
index 0000000000..559e4efd56
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/Server.java
@@ -0,0 +1,41 @@
+package com.baeldung.scopedvalues.scoped;
+
+import com.baeldung.scopedvalues.data.User;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jdk.incubator.concurrent.ScopedValue;
+
+import java.util.List;
+import java.util.Optional;
+
+public class Server {
+
+ private static final List AUTHENTICATED_USERS = List.of(
+ new User("1", "admin", "123456", true),
+ new User("2", "user", "123456", false)
+ );
+ public final static ScopedValue LOGGED_IN_USER = ScopedValue.newInstance();
+ private final Controller controller = new Controller();
+
+ public void serve(HttpServletRequest request, HttpServletResponse response) {
+ Optional user = authenticateUser(request);
+ if (user.isPresent()) {
+ ScopedValue.where(LOGGED_IN_USER, user.get())
+ .run(() -> controller.processRequest(request, response));
+ } else {
+ response.setStatus(401);
+ }
+ }
+
+ private Optional authenticateUser(HttpServletRequest request) {
+ return AUTHENTICATED_USERS.stream()
+ .filter(user -> checkUserPassword(user, request))
+ .findFirst();
+ }
+
+ private boolean checkUserPassword(User user, HttpServletRequest request) {
+ return user.name().equals(request.getParameter("user_name"))
+ && user.password().equals(request.getParameter("user_pw"));
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/Service.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/Service.java
new file mode 100644
index 0000000000..e35d98cae5
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/Service.java
@@ -0,0 +1,23 @@
+package com.baeldung.scopedvalues.scoped;
+
+import com.baeldung.scopedvalues.data.Data;
+import com.baeldung.scopedvalues.data.User;
+import jakarta.servlet.http.HttpServletRequest;
+
+import java.util.Optional;
+
+public class Service {
+
+ private final Repository repository = new Repository();
+
+ public Optional getData(HttpServletRequest request) {
+ String id = request.getParameter("data_id");
+ return repository.getData(id);
+ }
+
+ public void extractData() {
+ User loggedInUser = Server.LOGGED_IN_USER.get();
+ assert loggedInUser == null;
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/Controller.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/Controller.java
new file mode 100644
index 0000000000..e4742c0998
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/Controller.java
@@ -0,0 +1,44 @@
+package com.baeldung.scopedvalues.scoped.inheriting;
+
+import com.baeldung.scopedvalues.data.Data;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jdk.incubator.concurrent.StructuredTaskScope;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class Controller {
+
+ private final InternalService internalService = new InternalService();
+ private final ExternalService externalService = new ExternalService();
+
+ public void processRequest(HttpServletRequest request, HttpServletResponse response) {
+ try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+ Future> internalData = scope.fork(() -> internalService.getData(request));
+ Future externalData = scope.fork(externalService::getData);
+ try {
+ scope.join();
+ scope.throwIfFailed();
+
+ Optional data = internalData.resultNow();
+ if (data.isPresent()) {
+ PrintWriter out = response.getWriter();
+ response.setContentType("application/json");
+ out.println(data.get());
+ out.print(externalData.resultNow());
+ out.flush();
+ response.setStatus(200);
+ } else {
+ response.setStatus(400);
+ }
+ } catch (InterruptedException | ExecutionException | IOException e) {
+ response.setStatus(500);
+ }
+ }
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/ExternalService.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/ExternalService.java
new file mode 100644
index 0000000000..88fa4dfb74
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/ExternalService.java
@@ -0,0 +1,9 @@
+package com.baeldung.scopedvalues.scoped.inheriting;
+
+public class ExternalService {
+
+ public String getData() {
+ return "External data";
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/InternalService.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/InternalService.java
new file mode 100644
index 0000000000..ace46b254c
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/InternalService.java
@@ -0,0 +1,17 @@
+package com.baeldung.scopedvalues.scoped.inheriting;
+
+import com.baeldung.scopedvalues.data.Data;
+import jakarta.servlet.http.HttpServletRequest;
+
+import java.util.Optional;
+
+public class InternalService {
+
+ private final Repository repository = new Repository();
+
+ public Optional getData(HttpServletRequest request) {
+ String id = request.getParameter("data_id");
+ return repository.getData(id);
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/Repository.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/Repository.java
new file mode 100644
index 0000000000..22d18b2fac
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/Repository.java
@@ -0,0 +1,17 @@
+package com.baeldung.scopedvalues.scoped.inheriting;
+
+import com.baeldung.scopedvalues.data.Data;
+import com.baeldung.scopedvalues.data.User;
+
+import java.util.Optional;
+
+public class Repository {
+
+ public Optional getData(String id) {
+ User loggedInUser = Server.LOGGED_IN_USER.get();
+ return loggedInUser.isAdmin()
+ ? Optional.of(new Data(id, "Title 1", "Description 1"))
+ : Optional.empty();
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/Server.java b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/Server.java
new file mode 100644
index 0000000000..5f04a1eedd
--- /dev/null
+++ b/core-java-modules/core-java-20/src/main/java/com/baeldung/scopedvalues/scoped/inheriting/Server.java
@@ -0,0 +1,41 @@
+package com.baeldung.scopedvalues.scoped.inheriting;
+
+import com.baeldung.scopedvalues.data.User;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jdk.incubator.concurrent.ScopedValue;
+
+import java.util.List;
+import java.util.Optional;
+
+public class Server {
+
+ private static final List AUTHENTICATED_USERS = List.of(
+ new User("1", "admin", "123456", true),
+ new User("2", "user", "123456", false)
+ );
+ public final static ScopedValue LOGGED_IN_USER = ScopedValue.newInstance();
+ private final Controller controller = new Controller();
+
+ public void serve(HttpServletRequest request, HttpServletResponse response) {
+ Optional user = authenticateUser(request);
+ if (user.isPresent()) {
+ ScopedValue.where(LOGGED_IN_USER, user.get())
+ .run(() -> controller.processRequest(request, response));
+ } else {
+ response.setStatus(401);
+ }
+ }
+
+ private Optional authenticateUser(HttpServletRequest request) {
+ return AUTHENTICATED_USERS.stream()
+ .filter(user -> checkUserPassword(user, request))
+ .findFirst();
+ }
+
+ private boolean checkUserPassword(User user, HttpServletRequest request) {
+ return user.name().equals(request.getParameter("user_name"))
+ && user.password().equals(request.getParameter("user_pw"));
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/test/java/com/baeldung/scopedvalues/classic/ServerUnitTest.java b/core-java-modules/core-java-20/src/test/java/com/baeldung/scopedvalues/classic/ServerUnitTest.java
new file mode 100644
index 0000000000..e0b9366c22
--- /dev/null
+++ b/core-java-modules/core-java-20/src/test/java/com/baeldung/scopedvalues/classic/ServerUnitTest.java
@@ -0,0 +1,52 @@
+package com.baeldung.scopedvalues.classic;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.concurrent.ExecutionException;
+
+import static org.mockito.Mockito.*;
+import static org.assertj.core.api.Assertions.*;
+@ExtendWith(MockitoExtension.class)
+public class ServerUnitTest {
+
+ @Mock
+ private HttpServletRequest request;
+
+ @Mock
+ private HttpServletResponse response;
+
+ private final StringWriter writer = new StringWriter();
+
+ private final Server server = new Server();
+
+ @Test
+ void givenMockedRequestWithAdminCredentials_whenServeMethodIsCalled_thenDataIsReturned() throws InterruptedException, IOException, ExecutionException {
+ when(request.getParameter("user_name")).thenReturn("admin");
+ when(request.getParameter("user_pw")).thenReturn("123456");
+ when(request.getParameter("data_id")).thenReturn("1");
+ when(response.getWriter()).thenReturn(new PrintWriter(writer));
+
+ server.serve(request, response);
+
+ assertThat(writer.toString()).isEqualTo("Data[id=1, title=Title 1, description=Description 1]");
+ }
+
+ @Test
+ void givenMockedRequestWithUserCredentials_whenServeMethodIsCalled_thenNoDataIsReturned() throws InterruptedException, ExecutionException {
+ when(request.getParameter("user_name")).thenReturn("user");
+ when(request.getParameter("user_pw")).thenReturn("123456");
+
+ server.serve(request, response);
+
+ assertThat(writer.toString()).isEqualTo("");
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/test/java/com/baeldung/scopedvalues/scoped/ServerUnitTest.java b/core-java-modules/core-java-20/src/test/java/com/baeldung/scopedvalues/scoped/ServerUnitTest.java
new file mode 100644
index 0000000000..034e6683e3
--- /dev/null
+++ b/core-java-modules/core-java-20/src/test/java/com/baeldung/scopedvalues/scoped/ServerUnitTest.java
@@ -0,0 +1,52 @@
+package com.baeldung.scopedvalues.scoped;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+public class ServerUnitTest {
+
+ @Mock
+ private HttpServletRequest request;
+
+ @Mock
+ private HttpServletResponse response;
+
+ private final StringWriter writer = new StringWriter();
+
+ private final Server server = new Server();
+
+ @Test
+ void givenMockedRequestWithAdminCredentials_whenServeMethodIsCalled_thenDataIsReturned() throws IOException {
+ when(request.getParameter("user_name")).thenReturn("admin");
+ when(request.getParameter("user_pw")).thenReturn("123456");
+ when(request.getParameter("data_id")).thenReturn("1");
+ when(response.getWriter()).thenReturn(new PrintWriter(writer));
+
+ server.serve(request, response);
+
+ assertThat(writer.toString()).isEqualTo("Data[id=1, title=Title 1, description=Description 1]");
+ }
+
+ @Test
+ void givenMockedRequestWithUserCredentials_whenServeMethodIsCalled_thenNoDataIsReturned() throws IOException {
+ when(request.getParameter("user_name")).thenReturn("user");
+ when(request.getParameter("user_pw")).thenReturn("123456");
+
+ server.serve(request, response);
+
+ assertThat(writer.toString()).isEqualTo("");
+ }
+
+}
diff --git a/core-java-modules/core-java-20/src/test/java/com/baeldung/scopedvalues/scoped/inheriting/ServerUnitTest.java b/core-java-modules/core-java-20/src/test/java/com/baeldung/scopedvalues/scoped/inheriting/ServerUnitTest.java
new file mode 100644
index 0000000000..230b017c18
--- /dev/null
+++ b/core-java-modules/core-java-20/src/test/java/com/baeldung/scopedvalues/scoped/inheriting/ServerUnitTest.java
@@ -0,0 +1,52 @@
+package com.baeldung.scopedvalues.scoped.inheriting;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+public class ServerUnitTest {
+
+ @Mock
+ private HttpServletRequest request;
+
+ @Mock
+ private HttpServletResponse response;
+
+ private final StringWriter writer = new StringWriter();
+
+ private final Server server = new Server();
+
+ @Test
+ void givenMockedRequestWithAdminCredentials_whenServeMethodIsCalled_thenDataIsReturned() throws IOException {
+ when(request.getParameter("user_name")).thenReturn("admin");
+ when(request.getParameter("user_pw")).thenReturn("123456");
+ when(request.getParameter("data_id")).thenReturn("1");
+ when(response.getWriter()).thenReturn(new PrintWriter(writer));
+
+ server.serve(request, response);
+
+ assertThat(writer.toString()).isEqualTo("Data[id=1, title=Title 1, description=Description 1]\nExternal data");
+ }
+
+ @Test
+ void givenMockedRequestWithUserCredentials_whenServeMethodIsCalled_thenNoDataIsReturned() throws IOException {
+ when(request.getParameter("user_name")).thenReturn("user");
+ when(request.getParameter("user_pw")).thenReturn("123456");
+
+ server.serve(request, response);
+
+ assertThat(writer.toString()).isEqualTo("");
+ }
+
+}