Skip to content

calling BlockingNettyContext.shutdown() does not clear handlers #90

@bclozel

Description

@bclozel

This issue is linked with spring-projects/spring-boot#9146
When trying to fix devtools support in Spring Boot (i.e. stopping the server, recreating a new Spring context and starting a new server - all that without stopping the JVM), I've found that disposing a server and starting a new one has not the expected behavior.

Here's a repro case that shows the behavior:

package com.example.demo;

import org.assertj.core.api.Assertions;
import org.junit.Test;
import reactor.ipc.netty.http.client.HttpClient;
import reactor.ipc.netty.http.client.HttpClientResponse;
import reactor.ipc.netty.http.server.HttpServer;
import reactor.ipc.netty.tcp.BlockingNettyContext;

import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class ReactorNettyRestart {

	@Test
	public void testRestart() {
		// start a first server with a handler that answers HTTP 200 OK
		BlockingNettyContext context = HttpServer.create(8080)
				.start((req, resp) -> resp.status(200).send());

		HttpClientResponse response = HttpClient.create(8080).get("/").block();

		// checking the response status, OK
		Assertions.assertThat(response.status().code()).isEqualTo(200);
		// dispose the Netty context and wait for the channel close
		context.shutdown();
		context.getContext().onClose().block();

		// create a totally new server instance, with a different handler that answers HTTP 201
		context = HttpServer.create(8080)
				.start((req, resp) -> resp.status(201).send());

		response = HttpClient.create(8080).get("/").block();

		// fails, response status is 200 and debugging shows the the previous handler is called
		Assertions.assertThat(response.status().code()).isEqualTo(201);
		context.shutdown();
		context.getContext().onClose().block();
	}

	@Test
	public void testRestartBlockingClient() {

		RestTemplate template = new RestTemplate();
		// start a first server with a handler that answers HTTP 200 OK
		BlockingNettyContext context = HttpServer.create(8080)
				.start((req, resp) -> resp.status(200).send());

		ResponseEntity<String> response = template.getForEntity("http://localhost:8080/", String.class);

		// checking the response status, OK
		Assertions.assertThat(response.getStatusCode().value()).isEqualTo(200);
		// dispose the Netty context and wait for the channel close
		context.shutdown();
		context.getContext().onClose().block();

		// create a totally new server instance, with a different handler that answers HTTP 201
		context = HttpServer.create(8080)
				.start((req, resp) -> resp.status(201).send());

		response = template.getForEntity("http://localhost:8080/", String.class);

		// fails, response status is 200 and debugging shows the the previous handler is called
		Assertions.assertThat(response.getStatusCode().value()).isEqualTo(201);
		context.shutdown();
		context.getContext().onClose().block();
	}

}

Am I misusing the HttpServer API?
Is there some state that I forgot to clear?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions