Skip to content

Commit 00a7d13

Browse files
committed
#2848 Requested changes implemented
1 parent 247bda8 commit 00a7d13

File tree

4 files changed

+96
-32
lines changed

4 files changed

+96
-32
lines changed

server-session/README.md

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
---
22
title: Server Session
3-
category: Architectural
3+
category: Behavioral
44
language: en
5+
tag:
6+
- Session Management
7+
- Session Tracking
8+
- Cookies
59
---
610

711
## Also known as
@@ -52,25 +56,32 @@ public class LoginHandler implements HttpHandler {
5256
}
5357

5458
@Override
55-
public void handle(HttpExchange exchange) throws IOException {
59+
public void handle(HttpExchange exchange) {
5660
// Generate session ID
5761
String sessionID = UUID.randomUUID().toString();
5862

5963
// Store session data (simulated)
6064
int newUser = sessions.size() + 1;
6165
sessions.put(sessionID, newUser);
6266
sessionCreationTimes.put(sessionID, Instant.now());
67+
LOGGER.info("User " + newUser + " created at time " + sessionCreationTimes.get(sessionID));
6368

6469
// Set session ID as cookie
6570
exchange.getResponseHeaders().add("Set-Cookie", "sessionID=" + sessionID);
6671

6772
// Send response
6873
String response = "Login successful!\n" +
6974
"Session ID: " + sessionID;
70-
exchange.sendResponseHeaders(200, response.length());
71-
OutputStream os = exchange.getResponseBody();
72-
os.write(response.getBytes());
73-
os.close();
75+
try {
76+
exchange.sendResponseHeaders(200, response.length());
77+
} catch (IOException e) {
78+
LOGGER.error("An error occurred: ", e);
79+
}
80+
try(OutputStream os = exchange.getResponseBody()) {
81+
os.write(response.getBytes());
82+
} catch(IOException e) {
83+
LOGGER.error("An error occurred: ", e);
84+
}
7485
}
7586
}
7687
```
@@ -96,7 +107,7 @@ public class LogoutHandler implements HttpHandler {
96107
}
97108

98109
@Override
99-
public void handle(HttpExchange exchange) throws IOException {
110+
public void handle(HttpExchange exchange) {
100111
// Get session ID from cookie
101112
String sessionID = exchange.getRequestHeaders().getFirst("Cookie").replace("sessionID=", "");
102113
String currentSessionID = sessions.get(sessionID) == null ? null : sessionID;
@@ -112,24 +123,36 @@ public class LogoutHandler implements HttpHandler {
112123
}
113124

114125
//Remove session
126+
if(currentSessionID != null)
127+
LOGGER.info("User " + sessions.get(currentSessionID) + " deleted!");
128+
else
129+
LOGGER.info("User already deleted!");
115130
sessions.remove(sessionID);
116131
sessionCreationTimes.remove(sessionID);
117-
exchange.sendResponseHeaders(200, response.length());
118-
OutputStream os = exchange.getResponseBody();
119-
os.write(response.getBytes());
120-
os.close();
132+
133+
try {
134+
exchange.sendResponseHeaders(200, response.length());
135+
} catch(IOException e) {
136+
LOGGER.error("An error has occurred: ", e);
137+
}
138+
139+
try(OutputStream os = exchange.getResponseBody()) {
140+
os.write(response.getBytes());
141+
} catch(IOException e) {
142+
LOGGER.error("An error has occurred: ", e);
143+
}
121144
}
122145
}
123146
```
124147

125148
Sessions are often given a maximum time in which they will be maintained. The sessionExpirationTask() creates a thread which runs every 1 minute to check for sessions that have exceeded the maximum amount of time, in this case 1 minute and removes the session data from the server's storage.
126149

127150
```java
128-
private static void startSessionExpirationTask() {
151+
private static void sessionExpirationTask() {
129152
new Thread(() -> {
130153
while (true) {
131154
try {
132-
System.out.println("Session expiration checker started...");
155+
LOGGER.info("Session expiration checker started...");
133156
Thread.sleep(SESSION_EXPIRATION_TIME); // Sleep for expiration time
134157
Instant currentTime = Instant.now();
135158
synchronized (sessions) {
@@ -144,9 +167,10 @@ Sessions are often given a maximum time in which they will be maintained. The se
144167
}
145168
}
146169
}
147-
System.out.println("Session expiration checker finished!");
170+
LOGGER.info("Session expiration checker finished!");
148171
} catch (InterruptedException e) {
149-
e.printStackTrace();
172+
LOGGER.error("An error occurred: ", e);
173+
Thread.currentThread().interrupt();
150174
}
151175
}
152176
}).start();

server-session/src/main/java/com/iluwatar/sessionserver/App.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,33 @@
44
import java.net.InetSocketAddress;
55
import java.time.Instant;
66
import java.util.*;
7-
import java.util.logging.Logger;
8-
97
import com.sun.net.httpserver.HttpServer;
8+
import lombok.extern.slf4j.Slf4j;
9+
10+
/**
11+
* The server session pattern is a behavioral design pattern concerned with assigning the responsibility
12+
* of storing session data on the server side. Within the context of stateless protocols like HTTP all
13+
* requests are isolated events independent of previous requests. In order to create sessions during
14+
* user-access for a particular web application various methods can be used, such as cookies. Cookies
15+
* are a small piece of data that can be sent between client and server on every request and response
16+
* so that the server can "remember" the previous requests. In general cookies can either store the session
17+
* data or the cookie can store a session identifier and be used to access appropriate data from a persistent
18+
* storage. In the latter case the session data is stored on the server-side and appropriate data is
19+
* identified by the cookie sent from a client's request.
20+
* This project demonstrates the latter case.
21+
* In the following example the ({@link App}) class starts a server and assigns ({@link LoginHandler})
22+
* class to handle login request. When a user logs in a session identifier is created and stored for future
23+
* requests in a list. When a user logs out the session identifier is deleted from the list along with
24+
* the appropriate user session data, which is handle by the ({@link LogoutHandler}) class.
25+
*/
1026

27+
@Slf4j
1128
public class App {
1229

1330
// Map to store session data (simulated using a HashMap)
1431
private static Map<String, Integer> sessions = new HashMap<>();
1532
private static Map<String, Instant> sessionCreationTimes = new HashMap<>();
1633
private static final long SESSION_EXPIRATION_TIME = 10000;
17-
private static Logger logger = Logger.getLogger(App.class.getName());
1834

1935
public static void main(String[] args) throws IOException {
2036
// Create HTTP server listening on port 8000
@@ -30,14 +46,14 @@ public static void main(String[] args) throws IOException {
3046
// Start background task to check for expired sessions
3147
sessionExpirationTask();
3248

33-
logger.info("Server started. Listening on port 8080...");
49+
LOGGER.info("Server started. Listening on port 8080...");
3450
}
3551

3652
private static void sessionExpirationTask() {
3753
new Thread(() -> {
3854
while (true) {
3955
try {
40-
logger.info("Session expiration checker started...");
56+
LOGGER.info("Session expiration checker started...");
4157
Thread.sleep(SESSION_EXPIRATION_TIME); // Sleep for expiration time
4258
Instant currentTime = Instant.now();
4359
synchronized (sessions) {
@@ -52,9 +68,9 @@ private static void sessionExpirationTask() {
5268
}
5369
}
5470
}
55-
logger.info("Session expiration checker finished!");
71+
LOGGER.info("Session expiration checker finished!");
5672
} catch (InterruptedException e) {
57-
e.printStackTrace();
73+
LOGGER.error("An error occurred: ", e);
5874
Thread.currentThread().interrupt();
5975
}
6076
}

server-session/src/main/java/com/iluwatar/sessionserver/LoginHandler.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.sun.net.httpserver.HttpExchange;
44
import com.sun.net.httpserver.HttpHandler;
5+
import lombok.extern.slf4j.Slf4j;
6+
import org.slf4j.Logger;
57

68
import java.io.IOException;
79
import java.io.OutputStream;
@@ -10,6 +12,7 @@
1012
import java.util.Map;
1113
import java.util.UUID;
1214

15+
@Slf4j
1316
public class LoginHandler implements HttpHandler {
1417

1518
private Map<String, Integer> sessions;
@@ -21,24 +24,31 @@ public LoginHandler(Map<String, Integer> sessions, Map<String, Instant> sessionC
2124
}
2225

2326
@Override
24-
public void handle(HttpExchange exchange) throws IOException {
27+
public void handle(HttpExchange exchange) {
2528
// Generate session ID
2629
String sessionID = UUID.randomUUID().toString();
2730

2831
// Store session data (simulated)
2932
int newUser = sessions.size() + 1;
3033
sessions.put(sessionID, newUser);
3134
sessionCreationTimes.put(sessionID, Instant.now());
35+
LOGGER.info("User " + newUser + " created at time " + sessionCreationTimes.get(sessionID));
3236

3337
// Set session ID as cookie
3438
exchange.getResponseHeaders().add("Set-Cookie", "sessionID=" + sessionID);
3539

3640
// Send response
3741
String response = "Login successful!\n" +
3842
"Session ID: " + sessionID;
39-
exchange.sendResponseHeaders(200, response.length());
40-
OutputStream os = exchange.getResponseBody();
41-
os.write(response.getBytes());
42-
os.close();
43+
try {
44+
exchange.sendResponseHeaders(200, response.length());
45+
} catch (IOException e) {
46+
LOGGER.error("An error occurred: ", e);
47+
}
48+
try(OutputStream os = exchange.getResponseBody()) {
49+
os.write(response.getBytes());
50+
} catch(IOException e) {
51+
LOGGER.error("An error occurred: ", e);
52+
}
4353
}
4454
}

server-session/src/main/java/com/iluwatar/sessionserver/LogoutHandler.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
import com.sun.net.httpserver.HttpExchange;
44
import com.sun.net.httpserver.HttpHandler;
5+
import lombok.extern.slf4j.Slf4j;
56

67
import java.io.IOException;
78
import java.io.OutputStream;
89
import java.time.Instant;
910
import java.util.Map;
1011

12+
@Slf4j
1113
public class LogoutHandler implements HttpHandler {
1214

1315
private Map<String, Integer> sessions;
@@ -19,7 +21,7 @@ public LogoutHandler(Map<String, Integer> sessions, Map<String, Instant> session
1921
}
2022

2123
@Override
22-
public void handle(HttpExchange exchange) throws IOException {
24+
public void handle(HttpExchange exchange) {
2325
// Get session ID from cookie
2426
String sessionID = exchange.getRequestHeaders().getFirst("Cookie").replace("sessionID=", "");
2527
String currentSessionID = sessions.get(sessionID) == null ? null : sessionID;
@@ -35,11 +37,23 @@ public void handle(HttpExchange exchange) throws IOException {
3537
}
3638

3739
//Remove session
40+
if(currentSessionID != null)
41+
LOGGER.info("User " + sessions.get(currentSessionID) + " deleted!");
42+
else
43+
LOGGER.info("User already deleted!");
3844
sessions.remove(sessionID);
3945
sessionCreationTimes.remove(sessionID);
40-
exchange.sendResponseHeaders(200, response.length());
41-
OutputStream os = exchange.getResponseBody();
42-
os.write(response.getBytes());
43-
os.close();
46+
47+
try {
48+
exchange.sendResponseHeaders(200, response.length());
49+
} catch(IOException e) {
50+
LOGGER.error("An error has occurred: ", e);
51+
}
52+
53+
try(OutputStream os = exchange.getResponseBody()) {
54+
os.write(response.getBytes());
55+
} catch(IOException e) {
56+
LOGGER.error("An error has occurred: ", e);
57+
}
4458
}
4559
}

0 commit comments

Comments
 (0)