diff --git a/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/requestmappings/RequestMappingsParser20.java b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/requestmappings/RequestMappingsParser20.java index fb1fbc27f..52f706527 100644 --- a/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/requestmappings/RequestMappingsParser20.java +++ b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/requestmappings/RequestMappingsParser20.java @@ -30,10 +30,10 @@ public class RequestMappingsParser20 { .getJSONObject(contextId) .getJSONObject("mappings"); JSONArray rmArray = null; - if (mappings.has("dispatcherServlets")) { + if (mappings.has("dispatcherServlets") && mappings.getJSONObject("dispatcherServlets").has("dispatcherServlet")) { // Regular Web starter endpoints RMs JMX beans format rmArray = mappings.getJSONObject("dispatcherServlets").getJSONArray("dispatcherServlet"); - } else if (mappings.has("dispatcherHandlers")) { + } else if (mappings.has("dispatcherHandlers") && mappings.getJSONObject("dispatcherHandlers").has("webHandler")) { // WebFlux endpoints RMs JMX bean format rmArray = mappings.getJSONObject("dispatcherHandlers").getJSONArray("webHandler"); } diff --git a/headless-services/commons/commons-boot-app-cli/src/test/java/org/springframework/ide/vscode/commons/boot/app/cli/Boot2xRequestMappingsTest.java b/headless-services/commons/commons-boot-app-cli/src/test/java/org/springframework/ide/vscode/commons/boot/app/cli/Boot2xRequestMappingsTest.java index 5d9c4e29d..424d47285 100644 --- a/headless-services/commons/commons-boot-app-cli/src/test/java/org/springframework/ide/vscode/commons/boot/app/cli/Boot2xRequestMappingsTest.java +++ b/headless-services/commons/commons-boot-app-cli/src/test/java/org/springframework/ide/vscode/commons/boot/app/cli/Boot2xRequestMappingsTest.java @@ -89,4 +89,45 @@ public class Boot2xRequestMappingsTest { .collect(Collectors.toSet()) ); } + + @Test + public void testWebEurekaRms() throws Exception { + String json = IOUtils.toString(Boot2xRequestMappingsTest.class.getResourceAsStream("/live-rm-beans/rms-boot2-web-eureka.json")); + Collection rms = RequestMappingsParser20.parse(new JSONObject(json)); + assertEquals(9, rms.size()); + + ImmutableSet expected = ImmutableSet.of( + "/error", + "/actuator", + "/actuator/health", + "/actuator/info", + "/welcome" + ); + assertEquals(expected, + rms.stream() + .flatMap(rm -> Arrays.stream(rm.getSplitPath())) + .collect(Collectors.toSet()) + ); + + } + + @Test + public void testWebFluxEurekaRms() throws Exception { + String json = IOUtils.toString(Boot2xRequestMappingsTest.class.getResourceAsStream("/live-rm-beans/rms-boot2-webflux-eureka.json")); + Collection rms = RequestMappingsParser20.parse(new JSONObject(json)); + assertEquals(6, rms.size()); + + ImmutableSet expected = ImmutableSet.of( + "/actuator", + "/actuator/health", + "/actuator/info", + "/welcome" + ); + assertEquals(expected, + rms.stream() + .flatMap(rm -> Arrays.stream(rm.getSplitPath())) + .collect(Collectors.toSet()) + ); + + } } diff --git a/headless-services/commons/commons-boot-app-cli/src/test/resources/live-rm-beans/rms-boot2-web-eureka.json b/headless-services/commons/commons-boot-app-cli/src/test/resources/live-rm-beans/rms-boot2-web-eureka.json new file mode 100644 index 000000000..a69ce71c4 --- /dev/null +++ b/headless-services/commons/commons-boot-app-cli/src/test/resources/live-rm-beans/rms-boot2-web-eureka.json @@ -0,0 +1,270 @@ +{ + "contexts": { + "welcome-messages-1": { + "mappings": { + "dispatcherServlets": { + "dispatcherServlet": [ + { + "handler": "ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/], class path resource []], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@22fd98a9]]", + "predicate": "/**/favicon.ico" + }, + { + "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map)", + "predicate": "{[/actuator/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}", + "details": { + "requestMappingConditions": { + "headers": [], + "methods": [ + "GET" + ], + "patterns": [ + "/actuator/health" + ], + "produces": [ + { + "negated": false, + "mediaType": "application/vnd.spring-boot.actuator.v2+json" + }, + { + "negated": false, + "mediaType": "application/json" + } + ], + "params": [], + "consumes": [] + }, + "handlerMethod": { + "name": "handle", + "className": "org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping.OperationHandler", + "descriptor": "(Ljavax/servlet/http/HttpServletRequest;Ljava/util/Map;)Ljava/lang/Object;" + } + } + }, + { + "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map)", + "predicate": "{[/actuator/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}", + "details": { + "requestMappingConditions": { + "headers": [], + "methods": [ + "GET" + ], + "patterns": [ + "/actuator/info" + ], + "produces": [ + { + "negated": false, + "mediaType": "application/vnd.spring-boot.actuator.v2+json" + }, + { + "negated": false, + "mediaType": "application/json" + } + ], + "params": [], + "consumes": [] + }, + "handlerMethod": { + "name": "handle", + "className": "org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping.OperationHandler", + "descriptor": "(Ljavax/servlet/http/HttpServletRequest;Ljava/util/Map;)Ljava/lang/Object;" + } + } + }, + { + "handler": "protected java.util.Map> org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping.links(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)", + "predicate": "{[/actuator],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}", + "details": { + "requestMappingConditions": { + "headers": [], + "methods": [ + "GET" + ], + "patterns": [ + "/actuator" + ], + "produces": [ + { + "negated": false, + "mediaType": "application/vnd.spring-boot.actuator.v2+json" + }, + { + "negated": false, + "mediaType": "application/json" + } + ], + "params": [], + "consumes": [] + }, + "handlerMethod": { + "name": "links", + "className": "org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping", + "descriptor": "(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)Ljava/util/Map;" + } + } + }, + { + "handler": "public com.example.demo.Greeting com.example.demo.WelcomeMessageServiceApplication.greeting()", + "predicate": "{[/welcome],methods=[GET]}", + "details": { + "requestMappingConditions": { + "headers": [], + "methods": [ + "GET" + ], + "patterns": [ + "/welcome" + ], + "produces": [], + "params": [], + "consumes": [] + }, + "handlerMethod": { + "name": "greeting", + "className": "com.example.demo.WelcomeMessageServiceApplication", + "descriptor": "()Lcom/example/demo/Greeting;" + } + } + }, + { + "handler": "public org.springframework.http.ResponseEntity> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)", + "predicate": "{[/error]}", + "details": { + "requestMappingConditions": { + "headers": [], + "methods": [], + "patterns": [ + "/error" + ], + "produces": [], + "params": [], + "consumes": [] + }, + "handlerMethod": { + "name": "error", + "className": "org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController", + "descriptor": "(Ljavax/servlet/http/HttpServletRequest;)Lorg/springframework/http/ResponseEntity;" + } + } + }, + { + "handler": "public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)", + "predicate": "{[/error],produces=[text/html]}", + "details": { + "requestMappingConditions": { + "headers": [], + "methods": [], + "patterns": [ + "/error" + ], + "produces": [ + { + "negated": false, + "mediaType": "text/html" + } + ], + "params": [], + "consumes": [] + }, + "handlerMethod": { + "name": "errorHtml", + "className": "org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController", + "descriptor": "(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)Lorg/springframework/web/servlet/ModelAndView;" + } + } + }, + { + "handler": "ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/webjars/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@474c937f]]", + "predicate": "/webjars/**" + }, + { + "handler": "ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@6a7b18f7]]", + "predicate": "/**" + } + ] + }, + "servletFilters": [ + { + "name": "webMvcMetricsFilter", + "className": "org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter", + "urlPatternMappings": [ + "/*" + ], + "servletNameMappings": [] + }, + { + "name": "requestContextFilter", + "className": "org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter", + "urlPatternMappings": [ + "/*" + ], + "servletNameMappings": [] + }, + { + "name": "Tomcat WebSocket (JSR356) Filter", + "className": "org.apache.tomcat.websocket.server.WsFilter", + "urlPatternMappings": [ + "/*" + ], + "servletNameMappings": [] + }, + { + "name": "httpPutFormContentFilter", + "className": "org.springframework.boot.web.servlet.filter.OrderedHttpPutFormContentFilter", + "urlPatternMappings": [ + "/*" + ], + "servletNameMappings": [] + }, + { + "name": "hiddenHttpMethodFilter", + "className": "org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter", + "urlPatternMappings": [ + "/*" + ], + "servletNameMappings": [] + }, + { + "name": "characterEncodingFilter", + "className": "org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter", + "urlPatternMappings": [ + "/*" + ], + "servletNameMappings": [] + }, + { + "name": "httpTraceFilter", + "className": "org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter", + "urlPatternMappings": [ + "/*" + ], + "servletNameMappings": [] + } + ], + "servlets": [ + { + "mappings": [], + "name": "default", + "className": "org.apache.catalina.servlets.DefaultServlet" + }, + { + "mappings": [ + "/" + ], + "name": "dispatcherServlet", + "className": "org.springframework.web.servlet.DispatcherServlet" + } + ] + }, + "parentId": "welcome-messages-1" + }, + "bootstrap": { + "mappings": { + "dispatcherServlets": {}, + "servletFilters": [], + "servlets": [] + } + } + } +} \ No newline at end of file diff --git a/headless-services/commons/commons-boot-app-cli/src/test/resources/live-rm-beans/rms-boot2-webflux-eureka.json b/headless-services/commons/commons-boot-app-cli/src/test/resources/live-rm-beans/rms-boot2-webflux-eureka.json new file mode 100644 index 000000000..50419fe7f --- /dev/null +++ b/headless-services/commons/commons-boot-app-cli/src/test/resources/live-rm-beans/rms-boot2-webflux-eureka.json @@ -0,0 +1,145 @@ +{ + "contexts": { + "welcome-messages-1": { + "mappings": { + "dispatcherHandlers": { + "webHandler": [ + { + "predicate": "{[/actuator/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}", + "handler": "public org.reactivestreams.Publisher> org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)", + "details": { + "requestMappingConditions": { + "headers": [], + "methods": [ + "GET" + ], + "patterns": [ + "/actuator/health" + ], + "produces": [ + { + "negated": false, + "mediaType": "application/vnd.spring-boot.actuator.v2+json" + }, + { + "negated": false, + "mediaType": "application/json" + } + ], + "params": [], + "consumes": [] + }, + "handlerMethod": { + "name": "handle", + "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler", + "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;" + } + } + }, + { + "predicate": "{[/actuator/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}", + "handler": "public org.reactivestreams.Publisher> org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)", + "details": { + "requestMappingConditions": { + "headers": [], + "methods": [ + "GET" + ], + "patterns": [ + "/actuator/info" + ], + "produces": [ + { + "negated": false, + "mediaType": "application/vnd.spring-boot.actuator.v2+json" + }, + { + "negated": false, + "mediaType": "application/json" + } + ], + "params": [], + "consumes": [] + }, + "handlerMethod": { + "name": "handle", + "className": "org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEndpointHandlerMapping.ReadOperationHandler", + "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Lorg/reactivestreams/Publisher;" + } + } + }, + { + "predicate": "{[/actuator],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}", + "handler": "protected java.util.Map> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping.links(org.springframework.web.server.ServerWebExchange)", + "details": { + "requestMappingConditions": { + "headers": [], + "methods": [ + "GET" + ], + "patterns": [ + "/actuator" + ], + "produces": [ + { + "negated": false, + "mediaType": "application/vnd.spring-boot.actuator.v2+json" + }, + { + "negated": false, + "mediaType": "application/json" + } + ], + "params": [], + "consumes": [] + }, + "handlerMethod": { + "name": "links", + "className": "org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping", + "descriptor": "(Lorg/springframework/web/server/ServerWebExchange;)Ljava/util/Map;" + } + } + }, + { + "predicate": "{[/welcome],methods=[GET]}", + "handler": "public com.example.demo.Greeting com.example.demo.WelcomeMessageServiceApplication.greeting()", + "details": { + "requestMappingConditions": { + "headers": [], + "methods": [ + "GET" + ], + "patterns": [ + "/welcome" + ], + "produces": [], + "params": [], + "consumes": [] + }, + "handlerMethod": { + "name": "greeting", + "className": "com.example.demo.WelcomeMessageServiceApplication", + "descriptor": "()Lcom/example/demo/Greeting;" + } + } + }, + { + "predicate": "/webjars/**", + "handler": "ResourceWebHandler [locations=[class path resource [META-INF/resources/webjars/]], resolvers=[org.springframework.web.reactive.resource.PathResourceResolver@7030aee8]]" + }, + { + "predicate": "/**", + "handler": "ResourceWebHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/]], resolvers=[org.springframework.web.reactive.resource.PathResourceResolver@2c2efafe]]" + } + ] + } + }, + "parentId": "welcome-messages-1" + }, + "bootstrap": { + "mappings": { + "dispatcherHandlers": {} + } + } + } +}