SpringWebFluxTestApplication.java 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright The OpenTelemetry Authors
  3. * SPDX-License-Identifier: Apache-2.0
  4. */
  5. package server;
  6. import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
  7. import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
  8. import static org.springframework.web.reactive.function.server.RouterFunctions.route;
  9. import io.opentelemetry.api.GlobalOpenTelemetry;
  10. import io.opentelemetry.api.trace.Tracer;
  11. import java.time.Duration;
  12. import org.springframework.boot.autoconfigure.SpringBootApplication;
  13. import org.springframework.context.annotation.Bean;
  14. import org.springframework.context.annotation.ComponentScan;
  15. import org.springframework.context.annotation.FilterType;
  16. import org.springframework.http.MediaType;
  17. import org.springframework.stereotype.Component;
  18. import org.springframework.web.reactive.function.BodyInserters;
  19. import org.springframework.web.reactive.function.server.RouterFunction;
  20. import org.springframework.web.reactive.function.server.ServerRequest;
  21. import org.springframework.web.reactive.function.server.ServerResponse;
  22. import reactor.core.publisher.Mono;
  23. @SpringBootApplication
  24. @ComponentScan(
  25. basePackages = {"server"},
  26. excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "server.base.*"))
  27. public class SpringWebFluxTestApplication {
  28. private static final Tracer tracer = GlobalOpenTelemetry.getTracer("test");
  29. @Bean
  30. RouterFunction<ServerResponse> echoRouterFunction(EchoHandler echoHandler) {
  31. return route(POST("/echo"), new EchoHandlerFunction(echoHandler));
  32. }
  33. @Bean
  34. RouterFunction<ServerResponse> greetRouterFunction(GreetingHandler greetingHandler) {
  35. return route(GET("/greet"), request -> greetingHandler.defaultGreet())
  36. .andRoute(GET("/greet/{name}"), greetingHandler::customGreet)
  37. .andRoute(GET("/greet/{name}/{word}"), greetingHandler::customGreetWithWord)
  38. .andRoute(GET("/double-greet"), request -> greetingHandler.doubleGreet())
  39. .andRoute(
  40. GET("/greet-delayed"),
  41. request -> greetingHandler.defaultGreet().delayElement(Duration.ofMillis(100)))
  42. .andRoute(
  43. GET("/greet-failfast/{id}"),
  44. request -> {
  45. throw new IllegalStateException("bad things happen");
  46. })
  47. .andRoute(
  48. GET("/greet-failmono/{id}"),
  49. request -> Mono.error(new IllegalStateException("bad things happen")))
  50. .andRoute(
  51. GET("/greet-traced-method/{id}"),
  52. request ->
  53. greetingHandler.intResponse(
  54. Mono.just(tracedMethod(Integer.parseInt(request.pathVariable("id"))))))
  55. .andRoute(
  56. GET("/greet-mono-from-callable/{id}"),
  57. request ->
  58. greetingHandler.intResponse(
  59. Mono.fromCallable(
  60. () -> tracedMethod(Integer.parseInt(request.pathVariable("id"))))))
  61. .andRoute(
  62. GET("/greet-delayed-mono/{id}"),
  63. request ->
  64. greetingHandler.intResponse(
  65. Mono.just(Integer.parseInt(request.pathVariable("id")))
  66. .delayElement(Duration.ofMillis(100))
  67. .map(SpringWebFluxTestApplication::tracedMethod)));
  68. }
  69. @Component
  70. public static class GreetingHandler {
  71. public static final String DEFAULT_RESPONSE = "HELLO";
  72. Mono<ServerResponse> defaultGreet() {
  73. return ServerResponse.ok()
  74. .contentType(MediaType.TEXT_PLAIN)
  75. .body(BodyInserters.fromObject(DEFAULT_RESPONSE));
  76. }
  77. Mono<ServerResponse> doubleGreet() {
  78. return ServerResponse.ok()
  79. .contentType(MediaType.TEXT_PLAIN)
  80. .body(BodyInserters.fromObject(DEFAULT_RESPONSE + DEFAULT_RESPONSE));
  81. }
  82. Mono<ServerResponse> customGreet(ServerRequest request) {
  83. return ServerResponse.ok()
  84. .contentType(MediaType.TEXT_PLAIN)
  85. .body(BodyInserters.fromObject(DEFAULT_RESPONSE + " " + request.pathVariable("name")));
  86. }
  87. Mono<ServerResponse> customGreetWithWord(ServerRequest request) {
  88. return ServerResponse.ok()
  89. .contentType(MediaType.TEXT_PLAIN)
  90. .body(
  91. BodyInserters.fromObject(
  92. DEFAULT_RESPONSE
  93. + " "
  94. + request.pathVariable("name")
  95. + " "
  96. + request.pathVariable("word")));
  97. }
  98. Mono<ServerResponse> intResponse(Mono<FooModel> mono) {
  99. return ServerResponse.ok()
  100. .contentType(MediaType.TEXT_PLAIN)
  101. .body(
  102. BodyInserters.fromPublisher(
  103. mono.map(i -> DEFAULT_RESPONSE + " " + i.getId()), String.class));
  104. }
  105. }
  106. private static FooModel tracedMethod(long id) {
  107. tracer.spanBuilder("tracedMethod").startSpan().end();
  108. return new FooModel(id, "tracedMethod");
  109. }
  110. }