1616
1717import org .junit .jupiter .api .AfterEach ;
1818import org .junit .jupiter .api .BeforeEach ;
19- import org .junit .jupiter .api .Disabled ;
2019import org .junit .jupiter .api .Test ;
2120import org .junit .jupiter .api .Timeout ;
2221
@@ -47,9 +46,9 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
4746
4847 private HttpServer server ;
4948
50- private AtomicReference <Integer > responseStatus = new AtomicReference <>(200 );
49+ private AtomicReference <Integer > serverResponseStatus = new AtomicReference <>(200 );
5150
52- private AtomicReference <String > sessionId = new AtomicReference <>(null );
51+ private AtomicReference <String > currentServerSessionId = new AtomicReference <>(null );
5352
5453 private AtomicReference <String > lastReceivedSessionId = new AtomicReference <>(null );
5554
@@ -60,32 +59,37 @@ void startServer() throws IOException {
6059 server = HttpServer .create (new InetSocketAddress (PORT ), 0 );
6160
6261 // Configure the /mcp endpoint with dynamic response
63- server .createContext ("/mcp" , exchange -> {
64- // Capture session ID from request if present
65- String requestSessionId = exchange .getRequestHeaders ().getFirst (HttpHeaders .MCP_SESSION_ID );
66- lastReceivedSessionId .set (requestSessionId );
62+ server .createContext ("/mcp" , httpExchange -> {
63+ if ("DELETE" .equals (httpExchange .getRequestMethod ())) {
64+ httpExchange .sendResponseHeaders (200 , 0 );
65+ }
66+ else {
67+ // Capture session ID from request if present
68+ String requestSessionId = httpExchange .getRequestHeaders ().getFirst (HttpHeaders .MCP_SESSION_ID );
69+ lastReceivedSessionId .set (requestSessionId );
6770
68- int status = responseStatus .get ();
71+ int status = serverResponseStatus .get ();
6972
70- // Set response headers
71- exchange .getResponseHeaders ().set ("Content-Type" , "application/json" );
73+ // Set response headers
74+ httpExchange .getResponseHeaders ().set ("Content-Type" , "application/json" );
7275
73- // Add session ID to response if configured
74- String responseSessionId = sessionId .get ();
75- if (responseSessionId != null ) {
76- exchange .getResponseHeaders ().set (HttpHeaders .MCP_SESSION_ID , responseSessionId );
77- }
76+ // Add session ID to response if configured
77+ String responseSessionId = currentServerSessionId .get ();
78+ if (responseSessionId != null ) {
79+ httpExchange .getResponseHeaders ().set (HttpHeaders .MCP_SESSION_ID , responseSessionId );
80+ }
7881
79- // Send response based on configured status
80- if (status == 200 ) {
81- String response = "{\" jsonrpc\" :\" 2.0\" ,\" result\" :{},\" id\" :\" test-id\" }" ;
82- exchange .sendResponseHeaders (200 , response .length ());
83- exchange .getResponseBody ().write (response .getBytes ());
84- }
85- else {
86- exchange .sendResponseHeaders (status , 0 );
82+ // Send response based on configured status
83+ if (status == 200 ) {
84+ String response = "{\" jsonrpc\" :\" 2.0\" ,\" result\" :{},\" id\" :\" test-id\" }" ;
85+ httpExchange .sendResponseHeaders (200 , response .length ());
86+ httpExchange .getResponseBody ().write (response .getBytes ());
87+ }
88+ else {
89+ httpExchange .sendResponseHeaders (status , 0 );
90+ }
8791 }
88- exchange .close ();
92+ httpExchange .close ();
8993 });
9094
9195 server .setExecutor (null );
@@ -107,10 +111,10 @@ void stopServer() {
107111 */
108112 @ Test
109113 void test404WithoutSessionId () {
110- responseStatus .set (404 );
111- sessionId .set (null ); // No session ID in response
114+ serverResponseStatus .set (404 );
115+ currentServerSessionId .set (null ); // No session ID in response
112116
113- var testMessage = createTestMessage ();
117+ var testMessage = createTestRequestMessage ();
114118
115119 StepVerifier .create (transport .sendMessage (testMessage ))
116120 .expectErrorMatches (throwable -> throwable instanceof McpTransportException
@@ -127,8 +131,8 @@ void test404WithoutSessionId() {
127131 @ Test
128132 void test404WithSessionId () {
129133 // First establish a session
130- responseStatus .set (200 );
131- sessionId .set ("test-session-123" );
134+ serverResponseStatus .set (200 );
135+ currentServerSessionId .set ("test-session-123" );
132136
133137 // Set up exception handler to verify session invalidation
134138 @ SuppressWarnings ("unchecked" )
@@ -139,12 +143,12 @@ void test404WithSessionId() {
139143 StepVerifier .create (transport .connect (msg -> msg )).verifyComplete ();
140144
141145 // Send initial message to establish session
142- var testMessage = createTestMessage ();
146+ var testMessage = createTestRequestMessage ();
143147 StepVerifier .create (transport .sendMessage (testMessage )).verifyComplete ();
144148
145149 // The session should now be established, next request will include session ID
146150 // Now return 404 for next request
147- responseStatus .set (404 );
151+ serverResponseStatus .set (404 );
148152
149153 // Send another message - should get SessionNotFoundException
150154 StepVerifier .create (transport .sendMessage (testMessage ))
@@ -163,10 +167,10 @@ void test404WithSessionId() {
163167 */
164168 @ Test
165169 void test400WithoutSessionId () {
166- responseStatus .set (400 );
167- sessionId .set (null ); // No session ID
170+ serverResponseStatus .set (400 );
171+ currentServerSessionId .set (null ); // No session ID
168172
169- var testMessage = createTestMessage ();
173+ var testMessage = createTestRequestMessage ();
170174
171175 StepVerifier .create (transport .sendMessage (testMessage ))
172176 .expectErrorMatches (throwable -> throwable instanceof McpTransportException
@@ -185,8 +189,8 @@ void test400WithoutSessionId() {
185189 @ Test
186190 void test400WithSessionId () {
187191 // First establish a session
188- responseStatus .set (200 );
189- sessionId .set ("test-session-456" );
192+ serverResponseStatus .set (200 );
193+ currentServerSessionId .set ("test-session-456" );
190194
191195 // Set up exception handler
192196 @ SuppressWarnings ("unchecked" )
@@ -197,12 +201,12 @@ void test400WithSessionId() {
197201 StepVerifier .create (transport .connect (msg -> msg )).verifyComplete ();
198202
199203 // Send initial message to establish session
200- var testMessage = createTestMessage ();
204+ var testMessage = createTestRequestMessage ();
201205 StepVerifier .create (transport .sendMessage (testMessage )).verifyComplete ();
202206
203207 // The session should now be established, next request will include session ID
204208 // Now return 400 for next request (simulating unknown session ID)
205- responseStatus .set (400 );
209+ serverResponseStatus .set (400 );
206210
207211 // Send another message - should get SessionNotFoundException
208212 StepVerifier .create (transport .sendMessage (testMessage ))
@@ -222,25 +226,27 @@ void test400WithSessionId() {
222226 @ Test
223227 void testSessionRecoveryAfter404 () {
224228 // First establish a session
225- responseStatus .set (200 );
226- sessionId .set ("session-1" );
229+ serverResponseStatus .set (200 );
230+ currentServerSessionId .set ("session-1" );
227231
228232 // Send initial message to establish session
229- var testMessage = createTestMessage ();
233+ var testMessage = createTestRequestMessage ();
230234 StepVerifier .create (transport .sendMessage (testMessage )).verifyComplete ();
231235
236+ assertThat (lastReceivedSessionId .get ()).isNull ();
237+
232238 // The session should now be established
233239 // Simulate session loss - return 404
234- responseStatus .set (404 );
240+ serverResponseStatus .set (404 );
235241
236242 // This should fail with SessionNotFoundException
237243 StepVerifier .create (transport .sendMessage (testMessage ))
238244 .expectError (McpTransportSessionNotFoundException .class )
239245 .verify ();
240246
241247 // Now server is back with new session
242- responseStatus .set (200 );
243- sessionId .set ("session-2" );
248+ serverResponseStatus .set (200 );
249+ currentServerSessionId .set ("session-2" );
244250 lastReceivedSessionId .set (null ); // Reset to verify new session
245251
246252 // Should be able to establish new session
@@ -270,7 +276,7 @@ void testReconnectErrorHandling() {
270276 String requestSessionId = exchange .getRequestHeaders ().getFirst (HttpHeaders .MCP_SESSION_ID );
271277
272278 if ("GET" .equals (method )) {
273- int status = responseStatus .get ();
279+ int status = serverResponseStatus .get ();
274280
275281 if (status == 404 && requestSessionId != null ) {
276282 // 404 with session ID - should trigger SessionNotFoundException
@@ -292,7 +298,7 @@ else if (status == 404) {
292298 else {
293299 // POST request handling
294300 exchange .getResponseHeaders ().set ("Content-Type" , "application/json" );
295- String responseSessionId = sessionId .get ();
301+ String responseSessionId = currentServerSessionId .get ();
296302 if (responseSessionId != null ) {
297303 exchange .getResponseHeaders ().set (HttpHeaders .MCP_SESSION_ID , responseSessionId );
298304 }
@@ -304,8 +310,8 @@ else if (status == 404) {
304310 });
305311
306312 // Test with session ID - should get SessionNotFoundException
307- responseStatus .set (200 );
308- sessionId .set ("sse-session-1" );
313+ serverResponseStatus .set (200 );
314+ currentServerSessionId .set ("sse-session-1" );
309315
310316 var transport = HttpClientStreamableHttpTransport .builder (HOST )
311317 .endpoint ("/mcp-sse" )
@@ -316,19 +322,19 @@ else if (status == 404) {
316322 StepVerifier .create (transport .connect (msg -> msg )).verifyComplete ();
317323
318324 // Send message to establish session
319- var testMessage = createTestMessage ();
325+ var testMessage = createTestRequestMessage ();
320326 StepVerifier .create (transport .sendMessage (testMessage )).verifyComplete ();
321327
322328 // Now simulate server returning 404 on reconnect
323- responseStatus .set (404 );
329+ serverResponseStatus .set (404 );
324330
325331 // This should trigger reconnect which will fail
326332 // The error should be handled internally and passed to exception handler
327333
328334 StepVerifier .create (transport .closeGracefully ()).verifyComplete ();
329335 }
330336
331- private McpSchema .JSONRPCRequest createTestMessage () {
337+ private McpSchema .JSONRPCRequest createTestRequestMessage () {
332338 var initializeRequest = new McpSchema .InitializeRequest (ProtocolVersions .MCP_2025_03_26 ,
333339 McpSchema .ClientCapabilities .builder ().roots (true ).build (),
334340 new McpSchema .Implementation ("Test Client" , "1.0.0" ));
0 commit comments