mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-20 22:23:52 +00:00
deps: Refactor dependencies (#3224)
* remove spring dep move junit, logging, mockito under dep mgmt * upgrade anti-corruption-layer deps * async method invocation * balking, bloc * bridge to bytecode * caching * callback - cqrs * component - health check * hexagonal - metadata mapping * rest of the patterns * remove checkstyle, take spotless into use
This commit is contained in:
@@ -34,22 +34,21 @@ import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* The server session pattern is a behavioral design pattern concerned with assigning the responsibility
|
||||
* of storing session data on the server side. Within the context of stateless protocols like HTTP all
|
||||
* requests are isolated events independent of previous requests. In order to create sessions during
|
||||
* user-access for a particular web application various methods can be used, such as cookies. Cookies
|
||||
* are a small piece of data that can be sent between client and server on every request and response
|
||||
* so that the server can "remember" the previous requests. In general cookies can either store the session
|
||||
* data or the cookie can store a session identifier and be used to access appropriate data from a persistent
|
||||
* storage. In the latter case the session data is stored on the server-side and appropriate data is
|
||||
* identified by the cookie sent from a client's request.
|
||||
* This project demonstrates the latter case.
|
||||
* In the following example the ({@link App}) class starts a server and assigns ({@link LoginHandler})
|
||||
* class to handle login request. When a user logs in a session identifier is created and stored for future
|
||||
* requests in a list. When a user logs out the session identifier is deleted from the list along with
|
||||
* the appropriate user session data, which is handle by the ({@link LogoutHandler}) class.
|
||||
* The server session pattern is a behavioral design pattern concerned with assigning the
|
||||
* responsibility of storing session data on the server side. Within the context of stateless
|
||||
* protocols like HTTP all requests are isolated events independent of previous requests. In order
|
||||
* to create sessions during user-access for a particular web application various methods can be
|
||||
* used, such as cookies. Cookies are a small piece of data that can be sent between client and
|
||||
* server on every request and response so that the server can "remember" the previous requests. In
|
||||
* general cookies can either store the session data or the cookie can store a session identifier
|
||||
* and be used to access appropriate data from a persistent storage. In the latter case the session
|
||||
* data is stored on the server-side and appropriate data is identified by the cookie sent from a
|
||||
* client's request. This project demonstrates the latter case. In the following example the ({@link
|
||||
* App}) class starts a server and assigns ({@link LoginHandler}) class to handle login request.
|
||||
* When a user logs in a session identifier is created and stored for future requests in a list.
|
||||
* When a user logs out the session identifier is deleted from the list along with the appropriate
|
||||
* user session data, which is handle by the ({@link LogoutHandler}) class.
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
public class App {
|
||||
|
||||
@@ -60,6 +59,7 @@ public class App {
|
||||
|
||||
/**
|
||||
* Main entry point.
|
||||
*
|
||||
* @param args arguments
|
||||
* @throws IOException ex
|
||||
*/
|
||||
@@ -81,31 +81,36 @@ public class App {
|
||||
}
|
||||
|
||||
private static void sessionExpirationTask() {
|
||||
new Thread(() -> {
|
||||
while (true) {
|
||||
try {
|
||||
LOGGER.info("Session expiration checker started...");
|
||||
Thread.sleep(SESSION_EXPIRATION_TIME); // Sleep for expiration time
|
||||
Instant currentTime = Instant.now();
|
||||
synchronized (sessions) {
|
||||
synchronized (sessionCreationTimes) {
|
||||
Iterator<Map.Entry<String, Instant>> iterator =
|
||||
sessionCreationTimes.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, Instant> entry = iterator.next();
|
||||
if (entry.getValue().plusMillis(SESSION_EXPIRATION_TIME).isBefore(currentTime)) {
|
||||
sessions.remove(entry.getKey());
|
||||
iterator.remove();
|
||||
new Thread(
|
||||
() -> {
|
||||
while (true) {
|
||||
try {
|
||||
LOGGER.info("Session expiration checker started...");
|
||||
Thread.sleep(SESSION_EXPIRATION_TIME); // Sleep for expiration time
|
||||
Instant currentTime = Instant.now();
|
||||
synchronized (sessions) {
|
||||
synchronized (sessionCreationTimes) {
|
||||
Iterator<Map.Entry<String, Instant>> iterator =
|
||||
sessionCreationTimes.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, Instant> entry = iterator.next();
|
||||
if (entry
|
||||
.getValue()
|
||||
.plusMillis(SESSION_EXPIRATION_TIME)
|
||||
.isBefore(currentTime)) {
|
||||
sessions.remove(entry.getKey());
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGGER.info("Session expiration checker finished!");
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.error("An error occurred: ", e);
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGGER.info("Session expiration checker finished!");
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.error("An error occurred: ", e);
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
})
|
||||
.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +33,7 @@ import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* LoginHandler.
|
||||
*/
|
||||
/** LoginHandler. */
|
||||
@Slf4j
|
||||
public class LoginHandler implements HttpHandler {
|
||||
|
||||
|
||||
@@ -32,9 +32,7 @@ import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* LogoutHandler.
|
||||
*/
|
||||
/** LogoutHandler. */
|
||||
@Slf4j
|
||||
public class LogoutHandler implements HttpHandler {
|
||||
|
||||
@@ -61,7 +59,7 @@ public class LogoutHandler implements HttpHandler {
|
||||
response = "Logout successful!\n" + "Session ID: " + currentSessionId;
|
||||
}
|
||||
|
||||
//Remove session
|
||||
// Remove session
|
||||
if (currentSessionId != null) {
|
||||
LOGGER.info("User " + sessions.get(currentSessionId) + " deleted!");
|
||||
} else {
|
||||
|
||||
@@ -38,22 +38,17 @@ import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/**
|
||||
* LoginHandlerTest.
|
||||
*/
|
||||
/** LoginHandlerTest. */
|
||||
public class LoginHandlerTest {
|
||||
|
||||
private LoginHandler loginHandler;
|
||||
//private Headers headers;
|
||||
// private Headers headers;
|
||||
private Map<String, Integer> sessions;
|
||||
private Map<String, Instant> sessionCreationTimes;
|
||||
|
||||
@Mock
|
||||
private HttpExchange exchange;
|
||||
@Mock private HttpExchange exchange;
|
||||
|
||||
/**
|
||||
* Setup tests.
|
||||
*/
|
||||
/** Setup tests. */
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -65,18 +60,20 @@ public class LoginHandlerTest {
|
||||
@Test
|
||||
public void testHandle() {
|
||||
|
||||
//assemble
|
||||
// assemble
|
||||
ByteArrayOutputStream outputStream =
|
||||
new ByteArrayOutputStream(); //Exchange object is mocked so OutputStream must be manually created
|
||||
when(exchange.getResponseHeaders()).thenReturn(
|
||||
new Headers()); //Exchange object is mocked so Header object must be manually created
|
||||
new ByteArrayOutputStream(); // Exchange object is mocked so OutputStream must be manually
|
||||
// created
|
||||
when(exchange.getResponseHeaders())
|
||||
.thenReturn(
|
||||
new Headers()); // Exchange object is mocked so Header object must be manually created
|
||||
when(exchange.getResponseBody()).thenReturn(outputStream);
|
||||
|
||||
//act
|
||||
// act
|
||||
loginHandler.handle(exchange);
|
||||
|
||||
//assert
|
||||
// assert
|
||||
String[] response = outputStream.toString().split("Session ID: ");
|
||||
assertEquals(sessions.entrySet().toArray()[0].toString().split("=1")[0], response[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,9 +38,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/**
|
||||
* LogoutHandlerTest.
|
||||
*/
|
||||
/** LogoutHandlerTest. */
|
||||
public class LogoutHandlerTest {
|
||||
|
||||
private LogoutHandler logoutHandler;
|
||||
@@ -48,12 +46,9 @@ public class LogoutHandlerTest {
|
||||
private Map<String, Integer> sessions;
|
||||
private Map<String, Instant> sessionCreationTimes;
|
||||
|
||||
@Mock
|
||||
private HttpExchange exchange;
|
||||
@Mock private HttpExchange exchange;
|
||||
|
||||
/**
|
||||
* Setup tests.
|
||||
*/
|
||||
/** Setup tests. */
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -61,25 +56,27 @@ public class LogoutHandlerTest {
|
||||
sessionCreationTimes = new HashMap<>();
|
||||
logoutHandler = new LogoutHandler(sessions, sessionCreationTimes);
|
||||
headers = new Headers();
|
||||
headers.add("Cookie",
|
||||
"sessionID=1234"); //Exchange object methods return Header Object but Exchange is mocked so Headers must be manually created
|
||||
headers.add(
|
||||
"Cookie",
|
||||
"sessionID=1234"); // Exchange object methods return Header Object but Exchange is mocked so
|
||||
// Headers must be manually created
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandler_SessionNotExpired() {
|
||||
|
||||
//assemble
|
||||
sessions.put("1234", 1); //Fake login details since LoginHandler isn't called
|
||||
sessionCreationTimes.put("1234",
|
||||
Instant.now()); //Fake login details since LoginHandler isn't called
|
||||
// assemble
|
||||
sessions.put("1234", 1); // Fake login details since LoginHandler isn't called
|
||||
sessionCreationTimes.put(
|
||||
"1234", Instant.now()); // Fake login details since LoginHandler isn't called
|
||||
when(exchange.getRequestHeaders()).thenReturn(headers);
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
when(exchange.getResponseBody()).thenReturn(outputStream);
|
||||
|
||||
//act
|
||||
// act
|
||||
logoutHandler.handle(exchange);
|
||||
|
||||
//assert
|
||||
// assert
|
||||
String[] response = outputStream.toString().split("Session ID: ");
|
||||
Assertions.assertEquals("1234", response[1]);
|
||||
Assertions.assertFalse(sessions.containsKey(response[1]));
|
||||
@@ -89,15 +86,15 @@ public class LogoutHandlerTest {
|
||||
@Test
|
||||
public void testHandler_SessionExpired() {
|
||||
|
||||
//assemble
|
||||
// assemble
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
when(exchange.getRequestHeaders()).thenReturn(headers);
|
||||
when(exchange.getResponseBody()).thenReturn(outputStream);
|
||||
|
||||
//act
|
||||
// act
|
||||
logoutHandler.handle(exchange);
|
||||
|
||||
//assert
|
||||
// assert
|
||||
String[] response = outputStream.toString().split("Session ID: ");
|
||||
Assertions.assertEquals("Session has already expired!", response[0]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user