From e8085016bafe7091d6e69ddacca1be5cee0cf53d Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Sun, 5 Jul 2015 20:06:44 -0700 Subject: [PATCH] Polish Actuator hypermedia support --- spring-boot-actuator-docs/pom.xml | 24 +-- .../src/main/asciidoc/autoconfig.adoc | 25 +-- .../src/main/asciidoc/beans.adoc | 9 +- .../src/main/asciidoc/configprops.adoc | 15 +- .../src/main/asciidoc/dump.adoc | 14 +- .../src/main/asciidoc/env.adoc | 12 +- .../src/main/asciidoc/health.adoc | 14 +- .../src/main/asciidoc/index.adoc | 145 ++++++++------ .../src/main/asciidoc/info.adoc | 8 +- .../src/main/asciidoc/mappings.adoc | 6 +- .../src/main/asciidoc/metrics.adoc | 12 +- .../src/main/asciidoc/trace.adoc | 10 +- .../test/EndpointDocumentation.java | 38 +++- .../test/HealthEndpointDocumentation.java | 33 ++- .../test/HypermediaEndpointDocumentation.java | 37 ++-- .../test/SpringBootHypermediaApplication.java | 17 ++ .../EndpointWebMvcAutoConfiguration.java | 6 +- ...EndpointWebMvcHypermediaConfiguration.java | 189 +++++++++--------- .../actuate/autoconfigure/LinksEnhancer.java | 64 ++++++ .../ManagementSecurityAutoConfiguration.java | 29 ++- .../endpoint/mvc/ActuatorDocsEndpoint.java | 55 ++--- .../endpoint/mvc/EnvironmentMvcEndpoint.java | 2 +- .../endpoint/mvc/HalBrowserEndpoint.java | 20 +- .../endpoint/mvc/HypermediaDisabled.java | 11 +- .../endpoint/mvc/JolokiaMvcEndpoint.java | 2 +- .../actuate/endpoint/mvc/LinksEnhancer.java | 61 ------ .../endpoint/mvc/LinksMvcEndpoint.java | 8 +- ...BrowserPathHypermediaIntegrationTests.java | 31 ++- ...ContextPathHypermediaIntegrationTests.java | 55 +++-- ...tomHomepageHypermediaIntegrationTests.java | 36 +++- .../EndpointMvcIntegrationTests.java | 22 +- .../EndpointWebMvcAutoConfigurationTests.java | 46 ++--- ...althMvcEndpointAutoConfigurationTests.java | 6 +- ...agementSecurityAutoConfigurationTests.java | 52 ++--- .../MinimalActuatorHypermediaApplication.java | 17 +- ...ContextPathHypermediaIntegrationTests.java | 30 ++- .../ServerPortHypermediaIntegrationTests.java | 27 ++- .../VanillaHypermediaIntegrationTests.java | 59 ++++-- .../mvc/EnvironmentMvcEndpointTests.java | 27 ++- .../JolokiaMvcEndpointContextPathTests.java | 22 +- .../endpoint/mvc/JolokiaMvcEndpointTests.java | 32 +-- .../endpoint/mvc/MetricsMvcEndpointTests.java | 31 ++- .../mvc/MvcEndpointCorsIntegrationTests.java | 57 +++--- .../asciidoc/production-ready-features.adoc | 19 +- .../pom.xml | 22 +- .../demo/SpringBootHypermediaApplication.java | 12 -- .../gson/SampleHypermediaGsonApplication.java | 29 +++ .../SpringBootHypermediaApplicationTests.java | 61 ------ .../SampleHypermediaGsonApplicationTests.java | 76 +++++++ .../spring-boot-sample-hypermedia-jpa/pom.xml | 22 +- .../java/demo/JpaHypermediaApplication.java | 13 -- .../{demo => sample/hypermedia/jpa}/Book.java | 11 +- .../hypermedia/jpa}/BookRepository.java | 7 +- .../jpa/SampleHypermediaJpaApplication.java | 29 +++ .../demo/JpaHypermediaApplicationTests.java | 18 -- .../SampleHypermediaJpaApplicationTests.java | 36 ++++ ...paApplicationVanillaIntegrationTests.java} | 37 +++- .../spring-boot-sample-hypermedia-ui/pom.xml | 22 +- .../demo/SpringBootHypermediaApplication.java | 12 -- .../ui/SampleHypermediaUiApplication.java | 28 +++ .../SpringBootHypermediaApplicationTests.java | 18 -- .../SampleHypermediaUiApplicationTests.java} | 41 ++-- .../spring-boot-sample-hypermedia/pom.xml | 21 +- .../demo/SpringBootHypermediaApplication.java | 12 -- .../SampleHypermediaApplication.java | 29 +++ .../SpringBootHypermediaApplicationTests.java | 18 -- ...leHypermediaApplicationHomePageTests.java} | 36 +++- 67 files changed, 1140 insertions(+), 905 deletions(-) create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/LinksEnhancer.java delete mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/LinksEnhancer.java delete mode 100644 spring-boot-samples/spring-boot-sample-hypermedia-gson/src/main/java/demo/SpringBootHypermediaApplication.java create mode 100644 spring-boot-samples/spring-boot-sample-hypermedia-gson/src/main/java/sample/hypermedia/gson/SampleHypermediaGsonApplication.java delete mode 100644 spring-boot-samples/spring-boot-sample-hypermedia-gson/src/test/java/demo/SpringBootHypermediaApplicationTests.java create mode 100644 spring-boot-samples/spring-boot-sample-hypermedia-gson/src/test/java/sample/hypermedia/gson/SampleHypermediaGsonApplicationTests.java delete mode 100644 spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/demo/JpaHypermediaApplication.java rename spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/{demo => sample/hypermedia/jpa}/Book.java (90%) rename spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/{demo => sample/hypermedia/jpa}/BookRepository.java (88%) create mode 100644 spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/sample/hypermedia/jpa/SampleHypermediaJpaApplication.java delete mode 100644 spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/demo/JpaHypermediaApplicationTests.java create mode 100644 spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/sample/hypermedia/jpa/SampleHypermediaJpaApplicationTests.java rename spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/{demo/VanillaHypermediaIntegrationTests.java => sample/hypermedia/jpa/SampleHypermediaJpaApplicationVanillaIntegrationTests.java} (65%) delete mode 100644 spring-boot-samples/spring-boot-sample-hypermedia-ui/src/main/java/demo/SpringBootHypermediaApplication.java create mode 100644 spring-boot-samples/spring-boot-sample-hypermedia-ui/src/main/java/sample/hypermedia/ui/SampleHypermediaUiApplication.java delete mode 100644 spring-boot-samples/spring-boot-sample-hypermedia-ui/src/test/java/demo/SpringBootHypermediaApplicationTests.java rename spring-boot-samples/spring-boot-sample-hypermedia-ui/src/test/java/{demo/HomePageHypermediaApplicationTests.java => sample/hypermedia/ui/SampleHypermediaUiApplicationTests.java} (61%) delete mode 100644 spring-boot-samples/spring-boot-sample-hypermedia/src/main/java/demo/SpringBootHypermediaApplication.java create mode 100644 spring-boot-samples/spring-boot-sample-hypermedia/src/main/java/sample/hypermedia/SampleHypermediaApplication.java delete mode 100644 spring-boot-samples/spring-boot-sample-hypermedia/src/test/java/demo/SpringBootHypermediaApplicationTests.java rename spring-boot-samples/spring-boot-sample-hypermedia/src/test/java/{demo/HomePageHypermediaApplicationTests.java => sample/hypermedia/SampleHypermediaApplicationHomePageTests.java} (62%) diff --git a/spring-boot-actuator-docs/pom.xml b/spring-boot-actuator-docs/pom.xml index 76e893ccb3..3e3d1b0e84 100644 --- a/spring-boot-actuator-docs/pom.xml +++ b/spring-boot-actuator-docs/pom.xml @@ -2,25 +2,24 @@ 4.0.0 - - spring-boot-actuator-docs - jar - - spring-boot-actuator-docs - Docs project for Spring Boot - org.springframework.boot spring-boot-parent 1.3.0.BUILD-SNAPSHOT + ../spring-boot-parent - + spring-boot-actuator-docs + Spring Boot Actuator Docs + Spring Boot Actuator Docs + + Pivotal Software, Inc. + http://www.spring.io + - UTF-8 - 1.7 + ${basedir}/.. - + org.springframework.boot spring-boot-starter-web @@ -36,6 +35,7 @@ spring-boot-starter-hateoas true + org.springframework.restdocs spring-restdocs @@ -53,7 +53,6 @@ test - @@ -113,5 +112,4 @@ - diff --git a/spring-boot-actuator-docs/src/main/asciidoc/autoconfig.adoc b/spring-boot-actuator-docs/src/main/asciidoc/autoconfig.adoc index 5208f8fd70..be4c278d03 100644 --- a/spring-boot-actuator-docs/src/main/asciidoc/autoconfig.adoc +++ b/spring-boot-actuator-docs/src/main/asciidoc/autoconfig.adoc @@ -1,20 +1,17 @@ === /autoconfig +This endpoint is a report on the Spring Boot auto-configuration process that happened when +your application started up. It lists all the `@Conditional` annotations that were +evaluated as the context started and in each case it gives an indication of if (and why) +the condition matched. A positive match results in a bean being included in the context, +and a negative result means the opposite (the beans's class may not even be loaded). -This endpoint is a report on the Spring Boot Autoconfiguration process -that happened when your application started up. It lists all the -`@Conditional` annotations that were evaluated as the context started -and in each case it gives an indication of if (and why) the condition -matched. A positive match results in a bean being included in the context, -and a negative result means the opposite (the beans's class may not even -be loaded). +The report is split into 2 parts, positive matches first, and then negative. If the +context is a hierarchy, there is also a separate report on the parent context with the +same format (and recursively up to the top of the hierarchy). -The report is split into 2 parts, positive matches first, and then negative. -If the context is a hierarchy, there is also a separate report on the parent -context with the same format (and recursively up to the top of the hierarchy). - -NOTE: the report is actually about `@Conditional` evaluation not autoconfiguration -per se, but most autoconfiguration features use `@Conditional` heavily, so there is -a lot of overlap. +NOTE: the report is actually about `@Conditional` evaluation not auto-configuration +per se, but most autoconfiguration features use `@Conditional` heavily, so there is a lot +of overlap. Example curl request: include::{generated}/autoconfig/curl-request.adoc[] diff --git a/spring-boot-actuator-docs/src/main/asciidoc/beans.adoc b/spring-boot-actuator-docs/src/main/asciidoc/beans.adoc index e725f3f21d..306f81dcbc 100644 --- a/spring-boot-actuator-docs/src/main/asciidoc/beans.adoc +++ b/spring-boot-actuator-docs/src/main/asciidoc/beans.adoc @@ -1,11 +1,8 @@ === /beans +This endpoint is a report on the Spring Boot `ApplicationContext`. It lists the beans in +the context and their dependencies, detailing the names and concrete classes of each bean. -This endpoint is a report on the Spring Boot `ApplicationContext`. It lists -the beans in the context and their dependencies, detailing the names and -concrete classes of each bean. - -NOTE: some beans are pure configuration (any class that is annotated -`@Configuration`). +NOTE: some beans are pure configuration (any class that is annotated `@Configuration`). Example curl request: include::{generated}/beans/curl-request.adoc[] diff --git a/spring-boot-actuator-docs/src/main/asciidoc/configprops.adoc b/spring-boot-actuator-docs/src/main/asciidoc/configprops.adoc index 32b3a5b990..0d0eedd625 100644 --- a/spring-boot-actuator-docs/src/main/asciidoc/configprops.adoc +++ b/spring-boot-actuator-docs/src/main/asciidoc/configprops.adoc @@ -1,13 +1,10 @@ === /configprops - -This endpoint is a report on the Spring Boot `@ConfigurationProperties` -beans. Beans with this annotation are bound to the `Environment` on -startup, so they reflect the externalised configuration of the application. -Beans are listed by name. -A bean that is added using `@EnableConfigurationProperties` will have -a conventional name: `.CONFIGURATION_PROPERTIES`, where -`` is the environment key prefix specified in the -`@ConfigurationProperties` annotation. +This endpoint is a report on the Spring Boot `@ConfigurationProperties` beans. Beans with +this annotation are bound to the `Environment` on startup, so they reflect the +externalised configuration of the application. Beans are listed by name. A bean that is +added using `@EnableConfigurationProperties` will have a conventional name: +`.CONFIGURATION_PROPERTIES`, where `` is the environment key prefix +specified in the `@ConfigurationProperties` annotation. Example curl request: include::{generated}/configprops/curl-request.adoc[] diff --git a/spring-boot-actuator-docs/src/main/asciidoc/dump.adoc b/spring-boot-actuator-docs/src/main/asciidoc/dump.adoc index 4a5ac589e4..0ff6fc7a41 100644 --- a/spring-boot-actuator-docs/src/main/asciidoc/dump.adoc +++ b/spring-boot-actuator-docs/src/main/asciidoc/dump.adoc @@ -1,13 +1,11 @@ === /dump +This endpoint is a thread dump: the result is a list of threads each with their name, +monitor state and stack. It is the same information as you would get from `kill -3` of a +running Java process. Can be very useful for detecting issues at runtime, especially +sluggish behaviour caused by threads blocked by slow or unavailable I/O (e.g. if a +connection pool is exhausted). -This endpoint is a thread dump: the result is a list of threads each with -their name, monitor state and stack. It is the same information as you would -get from `kill -3` of a running Java process. Can be very useful for detecting -issues at runtime, especially sluggish behaviour caused by threads blocked -by slow or unavailable I/O (e.g. if a connection pool is exhausted). - -NOTE: some `SecurityManager` implementations might prevent this endpoint -from working. +NOTE: some `SecurityManager` implementations might prevent this endpoint from working. Example curl request: include::{generated}/dump/curl-request.adoc[] diff --git a/spring-boot-actuator-docs/src/main/asciidoc/env.adoc b/spring-boot-actuator-docs/src/main/asciidoc/env.adoc index c0266a0c1b..939d684ea5 100644 --- a/spring-boot-actuator-docs/src/main/asciidoc/env.adoc +++ b/spring-boot-actuator-docs/src/main/asciidoc/env.adoc @@ -1,11 +1,9 @@ === /env - -This endpoint is a dump of the Spring `Environment`. It lists the active -profiles and all the `PropertySources` in the `Environment` (the ones that -are listed first take precedence when binding to `@ConfigurationProperties` -or `@Value`). Normally you will see the Java `System` properties and the -OS environment variables in their own `PropertySources` plus any `.properties` -or `.yml` files used to configure the application on start up. +This endpoint is a dump of the Spring `Environment`. It lists the active profiles and all +the `PropertySources` in the `Environment` (the ones that are listed first take precedence +when binding to `@ConfigurationProperties` or `@Value`). Normally you will see the Java +`System` properties and the OS environment variables in their own `PropertySources` plus +any `.properties` or `.yml` files used to configure the application on start up. Example curl request: include::{generated}/env/curl-request.adoc[] diff --git a/spring-boot-actuator-docs/src/main/asciidoc/health.adoc b/spring-boot-actuator-docs/src/main/asciidoc/health.adoc index 54a292378d..10bde41e79 100644 --- a/spring-boot-actuator-docs/src/main/asciidoc/health.adoc +++ b/spring-boot-actuator-docs/src/main/asciidoc/health.adoc @@ -1,13 +1,11 @@ === /health +This endpoint is an indication of the health of the application. It has an overall status +("UP", "DOWN" etc.), which is the only thing you see unless either you are authenticated +or the endpoint is marked as `sensitive=false` (`endpoints.health.sensitive=false`). -This endpoint is an indication of the health of the application. -It has an overall status ("UP", "DOWN" etc.), which is the only thing -you see unless either you are authenticated or the endpoint is marked -as `sensitive=false` (`endpoints.health.sensitive=false`). - -The HTTP code in the response reflects the status (e.g. "UP" = 200, -"OUT_OF_SERVICE"=503, "DOWN"=503). The mappings can be changed by -configuring `endpoints.health.mapping.=XXX`. +The HTTP code in the response reflects the status (e.g. "`UP`"=200, +"`OUT_OF_SERVICE`"=503, "`DOWN`"=503). The mappings can be changed by configuring +`endpoints.health.mapping.=XXX`. Example curl request: include::{generated}/health/curl-request.adoc[] diff --git a/spring-boot-actuator-docs/src/main/asciidoc/index.adoc b/spring-boot-actuator-docs/src/main/asciidoc/index.adoc index b56959055b..78112b7ca2 100644 --- a/spring-boot-actuator-docs/src/main/asciidoc/index.adoc +++ b/spring-boot-actuator-docs/src/main/asciidoc/index.adoc @@ -10,12 +10,14 @@ The way that endpoints are exposed will depend on the type of technology that yo Most applications choose HTTP monitoring, where the ID of the endpoint is mapped to a URL. For example, by default, the `health` endpoint will be mapped to `/health`. -== List of Endpoints + +== List of Endpoints include::{generated}/endpoints.adoc[] -=== /logfile + +=== /logfile This endpoint (if available) contains the plain text logfile configured by the user using `logging.file` or `logging.path` (by default logs are only emitted on stdout so one of these properties has to be set for this endpoint to be active). @@ -29,21 +31,23 @@ include::{generated}/logfile/http-request.adoc[] Example HTTP response: include::{generated}/logfile/http-response.adoc[] -=== /docs + +=== /docs This endpoint (if available) contains HTML documemtation for the other endpoints. Its path -can be "/docs" (if there is an existing home page) or "/" (otherwise, including if the +can be "/docs" (if there is an existing home page) or "/" (otherwise, including if the HAL browser is not active). -== Hypermedia Support -If https://projects.spring.io/spring-hateoas[Spring HATEOAS] is enabled -(i.e. if it is on the classpath by default) then the Actuator -endpoint responses are enhanced with hypermedia in the form of "links". The default -media type for responses is http://stateless.co/hal_specification.html[HAL], resulting -in each resource having an extra property called "_links". You can change the -media type to another one supported by Spring HATEOAS by providing your own -`@EnableHypermedia` annotation and custom providers as necessary. + +== Hypermedia Support +If https://projects.spring.io/spring-hateoas[Spring HATEOAS] is enabled (i.e. if it is +on the classpath by default) then the Actuator endpoint responses are enhanced with +hypermedia in the form of "links". The default media type for responses is +http://stateless.co/hal_specification.html[HAL], resulting in each resource having an +extra property called "_links". You can change the media type to another one supported by +Spring HATEOAS by providing your own `@EnableHypermedia` annotation and custom providers +as necessary. Example enhanced "/metrics" endpoint with additional "_links": @@ -55,94 +59,103 @@ The easiest way to avoid that is to use a `management.contextPath`, e.g. "/admin TIP: You can disable the hypermedia support in Actuator endpoints by setting `endpoints.links.enabled=false`. -=== Default home page -If the `management.contextPath` is empty, or if the home page provided -by the application happens to be a response body of type `ResourceSupport`, then it will -be enhanced with links to the actuator endpoints. The latter would happen for instance -if you use Spring Data REST to expose `Repository` endpoints. -Example vanilla "/" endpoint if the `management.contextPath` is empty (the "/admin" -page would be the same with different links if `management.contextPath=/admin`): + +=== Default home page +If the `management.contextPath` is empty, or if the home page provided by the application +happens to be a response body of type `ResourceSupport`, then it will be enhanced with +links to the actuator endpoints. The latter would happen for instance if you use Spring +Data REST to expose `Repository` endpoints. + +Example vanilla "/" endpoint if the `management.contextPath` is empty (the "/admin" page +would be the same with different links if `management.contextPath=/admin`): include::{generated}/admin/http-response.adoc[] -=== Endpoints with format changes -Some endpoints in their "raw" form consist of an array (e.g. the "/beans" and the "/trace" endpoints). -These need to be converted to objects (maps) before they can be enhanced with -links, so their contents are inserted as a field named "content". -Example enhanced "/beans" endpoint with additional "_links": + + +=== Endpoints with format changes +Some endpoints in their "`raw`" form consist of an array (e.g. the `/beans` and the +`/trace` endpoints). These need to be converted to objects (maps) before they can be +enhanced with links, so their contents are inserted as a field named "`content`". +Example enhanced `/beans` endpoint with additional `_links`: include::{generated}/beans/hypermedia/http-response.adoc[] -== HAL Browser -If Hypermedia is enabled and the HAL format is in use (which is the default), then -you can provide a browser for the resources by including a dependency -on the https://github.com/mikekelly/hal-browser[HAL browser] webjar. + +== HAL Browser +If Hypermedia is enabled and the HAL format is in use (which is the default), then you +can provide a browser for the resources by including a dependency on the +https://github.com/mikekelly/hal-browser[HAL browser] webjar. + For example in Maven: -[source,xml] +[source,xml,indent=0] ---- - - org.webjars - hal-browser - + + org.webjars + hal-browser + ---- or in Gradle -[source,groovy] +[source,groovy,indent=0] ---- -dependencies { - ... - compile('org.webjars:hal-browser') - ... -} + dependencies { + ... + compile('org.webjars:hal-browser') + ... + } ---- -NOTE: if you are using Spring Data REST, then a dependency on the `spring-data-rest-hal-browser` -will have an equivalent effect. +NOTE: if you are using Spring Data REST, then a dependency on the +`spring-data-rest-hal-browser` will have an equivalent effect. -If you do that then a new endpoint will appear at "/" or "/hal" (relative to the `management.contextPath`) -serving up a static HTML page with some JavaScript that lets you browse the available -resources. The default endpoint path depends on whether or not there is already a static home page -("index.html") - if there is not and the `management.contextPath` is empty, then the HAL browser -shows up on the home page. Example: +If you do that then a new endpoint will appear at `/` or `/hal` (relative to the +`management.contextPath`) serving up a static HTML page with some JavaScript that lets you +browse the available resources. The default endpoint path depends on whether or not there +is already a static home page ("`index.html`") - if there is not and the +`management.contextPath` is empty, then the HAL browser shows up on the home page. + +Example: image::hal-browser.png[HAL Browser] TIP: The endpoint path can always, as with all MVC endpoints, be overridden using -`endpoints.hal.path=/yourpath` (note the leading slash). +`endpoints.hal.path=/yourpath` (note the leading slash). + + == Actuator Documentation Browser +You can also provide a browser for the standard generated documentation for the Actuator +endpoints by including a dependency on the documentation jar. -You can also provide a browser for the standard generated documentation -for the Actuator endpoints by including a dependency on the documentation jar. For example in Maven: -[source,xml] +[source,xml,indent=0] ---- - - org.springframework.boot - spring-boot-hypermedia-docs - + + org.springframework.boot + spring-boot-hypermedia-docs + ---- - or in Gradle -[source,groovy] +[source,groovy,indent=0] ---- -dependencies { - ... - compile('org.springframework.boot:spring-boot-hypermedia-docs') - ... -} + dependencies { + ... + compile('org.springframework.boot:spring-boot-hypermedia-docs') + ... + } ---- -If you do that then a new endpoint at "/" or "/docs" (relative to the `management.contextPath`) -will serve up a static HTML page with this documentation in it. The default endpoint path depends -on whether or not there is already a static home page -("index.html" or a HAL browser) - if there is not and the `management.contextPath` is empty, -then the docs browser shows up on the home page. \ No newline at end of file +If you do that then a new endpoint at `/` or `/docs` (relative to the +`management.contextPath`) will serve up a static HTML page with this documentation in it. +The default endpoint path depends on whether or not there is already a static home page +("index.html" or a HAL browser) - if there is not and the `management.contextPath` is +empty, then the docs browser shows up on the home page. diff --git a/spring-boot-actuator-docs/src/main/asciidoc/info.adoc b/spring-boot-actuator-docs/src/main/asciidoc/info.adoc index af1c191462..981095184a 100644 --- a/spring-boot-actuator-docs/src/main/asciidoc/info.adoc +++ b/spring-boot-actuator-docs/src/main/asciidoc/info.adoc @@ -1,9 +1,7 @@ === /info - -This endpoint is empty and marked as `sensitive=false` -by default (so it is unauthenticated by default if Spring -Security is in use). It reflects the content of the `info.*` properties -in the `Environment`, as well as the properties in `git.properties` +This endpoint is empty and marked as `sensitive=false` by default (so it is +unauthenticated by default if Spring Security is in use). It reflects the content of the +`info.*` properties in the `Environment`, as well as the properties in `git.properties` if such a file exists in the root of the classpath. Example curl request: diff --git a/spring-boot-actuator-docs/src/main/asciidoc/mappings.adoc b/spring-boot-actuator-docs/src/main/asciidoc/mappings.adoc index 685d227231..7e47b17983 100644 --- a/spring-boot-actuator-docs/src/main/asciidoc/mappings.adoc +++ b/spring-boot-actuator-docs/src/main/asciidoc/mappings.adoc @@ -1,8 +1,6 @@ === /mappings - -This endpoint lists the Spring MVC request mappings, so users can -see the handlers registered for requests by path, method, media type, -etc. +This endpoint lists the Spring MVC request mappings, so users can see the handlers +registered for requests by path, method, media type, etc. Example curl request: include::{generated}/mappings/curl-request.adoc[] diff --git a/spring-boot-actuator-docs/src/main/asciidoc/metrics.adoc b/spring-boot-actuator-docs/src/main/asciidoc/metrics.adoc index 42c61f6c34..f67b2d9d4c 100644 --- a/spring-boot-actuator-docs/src/main/asciidoc/metrics.adoc +++ b/spring-boot-actuator-docs/src/main/asciidoc/metrics.adoc @@ -1,11 +1,9 @@ === /metrics - -This endpoint lists the public metrics exposed by the application. -By default this includes all the counters in the `CounterService` -and all the gauges in the `GaugeService`, plus a few JVM metrics about -memory and uptime. Users can register additional sources by creating -beans of type `PublicMetrics` and/or by registering counters and -gauges. +This endpoint lists the public metrics exposed by the application. By default this +includes all the counters in the `CounterService` and all the gauges in the +`GaugeService`, plus a few JVM metrics about memory and uptime. Users can register +additional sources by creating beans of type `PublicMetrics` and/or by registering +counters and gauges. Example curl request: include::{generated}/metrics/curl-request.adoc[] diff --git a/spring-boot-actuator-docs/src/main/asciidoc/trace.adoc b/spring-boot-actuator-docs/src/main/asciidoc/trace.adoc index c35b66a829..8edc75fb0d 100644 --- a/spring-boot-actuator-docs/src/main/asciidoc/trace.adoc +++ b/spring-boot-actuator-docs/src/main/asciidoc/trace.adoc @@ -1,10 +1,8 @@ === /trace - -This endpoint lists contents of the `TraceRepository` (which -users can override by providing a bean of that type, or by -injecting that bean and adding stuff to it). By default -it is the last 100 HTTP requests, including all headers in the -request and response, and the path and HTTP status. +This endpoint lists contents of the `TraceRepository` (which users can override by +providing a bean of that type, or by injecting that bean and adding stuff to it). By +default it is the last 100 HTTP requests, including all headers in the request and +response, and the path and HTTP status. Example curl request: include::{generated}/trace/curl-request.adoc[] diff --git a/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/EndpointDocumentation.java b/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/EndpointDocumentation.java index 1b02d66ea4..ee3c400be5 100644 --- a/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/EndpointDocumentation.java +++ b/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/EndpointDocumentation.java @@ -1,9 +1,21 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.boot.actuate.hypermedia.test; -import static org.springframework.restdocs.RestDocumentation.document; -import static org.springframework.restdocs.RestDocumentation.documentationConfiguration; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import groovy.text.Template; import groovy.text.TemplateEngine; @@ -40,6 +52,11 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.util.StringUtils; import org.springframework.web.context.WebApplicationContext; +import static org.springframework.restdocs.RestDocumentation.document; +import static org.springframework.restdocs.RestDocumentation.documentationConfiguration; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = SpringBootHypermediaApplication.class) @WebAppConfiguration @@ -82,8 +99,7 @@ public class EndpointDocumentation { @Test public void logfile() throws Exception { this.mockMvc.perform(get("/logfile").accept(MediaType.TEXT_PLAIN)) - .andExpect(status().isOk()) - .andDo(document("logfile")); + .andExpect(status().isOk()).andDo(document("logfile")); } @Test @@ -98,10 +114,10 @@ public class EndpointDocumentation { final String endpointPath = StringUtils.hasText(endpoint.getPath()) ? endpoint .getPath() : "/"; - if (!endpointPath.equals("/docs") && !endpointPath.equals("/logfile")) { - String output = endpointPath.substring(1); - output = output.length() > 0 ? output : "./"; - this.mockMvc + if (!endpointPath.equals("/docs") && !endpointPath.equals("/logfile")) { + String output = endpointPath.substring(1); + output = output.length() > 0 ? output : "./"; + this.mockMvc .perform(get(endpointPath).accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()).andDo(document(output)) .andDo(new ResultHandler() { @@ -111,7 +127,7 @@ public class EndpointDocumentation { endpoints.add(endpoint); } }); - } + } } File file = new File(this.restdocsOutputDir + "/endpoints.adoc"); file.getParentFile().mkdirs(); diff --git a/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/HealthEndpointDocumentation.java b/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/HealthEndpointDocumentation.java index d9f6ba26cf..58944d9649 100644 --- a/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/HealthEndpointDocumentation.java +++ b/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/HealthEndpointDocumentation.java @@ -1,9 +1,21 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.boot.actuate.hypermedia.test; -import static org.springframework.restdocs.RestDocumentation.document; -import static org.springframework.restdocs.RestDocumentation.documentationConfiguration; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import groovy.text.TemplateEngine; import org.junit.Before; @@ -22,11 +34,16 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import static org.springframework.restdocs.RestDocumentation.document; +import static org.springframework.restdocs.RestDocumentation.documentationConfiguration; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = SpringBootHypermediaApplication.class) @WebAppConfiguration @TestPropertySource(properties = { "spring.jackson.serialization.indent_output=true", -"endpoints.health.sensitive=false" }) + "endpoints.health.sensitive=false" }) @DirtiesContext public class HealthEndpointDocumentation { @@ -49,15 +66,13 @@ public class HealthEndpointDocumentation { System.setProperty("org.springframework.restdocs.outputDir", this.restdocsOutputDir); this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) - .apply(documentationConfiguration()) - .build(); + .apply(documentationConfiguration()).build(); } @Test public void health() throws Exception { this.mockMvc.perform(get("/health").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(document("health/unsensitive")); + .andExpect(status().isOk()).andDo(document("health/unsensitive")); } } diff --git a/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/HypermediaEndpointDocumentation.java b/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/HypermediaEndpointDocumentation.java index 1ca6a2e2ae..24a88d780f 100644 --- a/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/HypermediaEndpointDocumentation.java +++ b/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/HypermediaEndpointDocumentation.java @@ -1,9 +1,21 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.boot.actuate.hypermedia.test; -import static org.springframework.restdocs.RestDocumentation.document; -import static org.springframework.restdocs.RestDocumentation.documentationConfiguration; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import groovy.text.TemplateEngine; import org.junit.Before; @@ -22,6 +34,11 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import static org.springframework.restdocs.RestDocumentation.document; +import static org.springframework.restdocs.RestDocumentation.documentationConfiguration; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = SpringBootHypermediaApplication.class) @WebAppConfiguration @@ -48,29 +65,25 @@ public class HypermediaEndpointDocumentation { System.setProperty("org.springframework.restdocs.outputDir", this.restdocsOutputDir); this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) - .apply(documentationConfiguration()) - .build(); + .apply(documentationConfiguration()).build(); } @Test public void beans() throws Exception { this.mockMvc.perform(get("/beans").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(document("beans/hypermedia")); + .andExpect(status().isOk()).andDo(document("beans/hypermedia")); } @Test public void metrics() throws Exception { this.mockMvc.perform(get("/metrics").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(document("metrics/hypermedia")); + .andExpect(status().isOk()).andDo(document("metrics/hypermedia")); } @Test public void home() throws Exception { this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(document("admin")); + .andExpect(status().isOk()).andDo(document("admin")); } } diff --git a/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/SpringBootHypermediaApplication.java b/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/SpringBootHypermediaApplication.java index 5a9ca58fe6..6c3418589e 100644 --- a/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/SpringBootHypermediaApplication.java +++ b/spring-boot-actuator-docs/src/test/java/org/springframework/boot/actuate/hypermedia/test/SpringBootHypermediaApplication.java @@ -1,3 +1,19 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.boot.actuate.hypermedia.test; import groovy.text.GStringTemplateEngine; @@ -18,4 +34,5 @@ public class SpringBootHypermediaApplication { public static void main(String[] args) { SpringApplication.run(SpringBootHypermediaApplication.class, args); } + } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java index bf7b3f9e3d..161d05e3f5 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java @@ -88,9 +88,9 @@ import org.springframework.web.servlet.DispatcherServlet; @ConditionalOnClass({ Servlet.class, DispatcherServlet.class }) @ConditionalOnWebApplication @AutoConfigureAfter({ PropertyPlaceholderAutoConfiguration.class, - EmbeddedServletContainerAutoConfiguration.class, WebMvcAutoConfiguration.class, - ManagementServerPropertiesAutoConfiguration.class, - HypermediaAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class }) + EmbeddedServletContainerAutoConfiguration.class, WebMvcAutoConfiguration.class, + ManagementServerPropertiesAutoConfiguration.class, + HypermediaAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class }) public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware, SmartInitializingSingleton { diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcHypermediaConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcHypermediaConfiguration.java index a387675fe9..c7bacf0497 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcHypermediaConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcHypermediaConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,21 +16,17 @@ package org.springframework.boot.actuate.autoconfigure; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; - import java.io.IOException; import java.lang.reflect.Type; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.endpoint.mvc.ActuatorDocsEndpoint; import org.springframework.boot.actuate.endpoint.mvc.HalBrowserEndpoint; import org.springframework.boot.actuate.endpoint.mvc.HypermediaDisabled; -import org.springframework.boot.actuate.endpoint.mvc.LinksEnhancer; import org.springframework.boot.actuate.endpoint.mvc.LinksMvcEndpoint; import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints; @@ -78,11 +74,13 @@ import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; + /** - * Autoconfiguration for hypermedia in HTTP endpoints. + * Configuration for hypermedia in HTTP endpoints. * * @author Dave Syer - * + * @since 1.3.0 */ @Configuration @ConditionalOnClass(Link.class) @@ -124,10 +122,14 @@ public class EndpointWebMvcHypermediaConfiguration { return new DefaultCurieProvider("boot", new UriTemplate(path)); } + /** + * {@link SpringBootCondition} to detect the Spring Data REST HAL browser. + */ @Configuration("EndpointHypermediaAutoConfiguration.MissingResourceCondition") @ConditionalOnResource(resources = "classpath:/META-INF/spring-data-rest/hal-browser/index.html") protected static class MissingSpringDataRestResourceCondition extends - SpringBootCondition { + SpringBootCondition { + @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { @@ -136,44 +138,46 @@ public class EndpointWebMvcHypermediaConfiguration { return ConditionOutcome.noMatch("Spring Data REST HAL browser found"); } return ConditionOutcome.match("Spring Data REST HAL browser not found"); + } + } + /** + * Configuration for Endpoint links. + */ @ConditionalOnProperty(value = "endpoints.links.enabled", matchIfMissing = true) public static class LinksConfiguration { @Bean public LinksMvcEndpoint linksMvcEndpoint(ResourceProperties resources) { - return new LinksMvcEndpoint(resources.getWelcomePage() != null ? "/links" - : ""); + String defaultPath = (resources.getWelcomePage() != null ? "/links" : ""); + return new LinksMvcEndpoint(defaultPath); } /** * Controller advice that adds links to the home page and/or the management * context path. The home page is enhanced if it is composed already of a * {@link ResourceSupport} (e.g. when using Spring Data REST). - * - * @author Dave Syer - * */ @ControllerAdvice public static class HomePageLinksAdvice implements ResponseBodyAdvice { @Autowired - MvcEndpoints endpoints; + private MvcEndpoints endpoints; @Autowired - LinksMvcEndpoint linksEndpoint; + private LinksMvcEndpoint linksEndpoint; @Autowired - ManagementServerProperties management; + private ManagementServerProperties management; private LinksEnhancer linksEnhancer; @PostConstruct public void init() { - this.linksEnhancer = new LinksEnhancer(this.endpoints, - this.management.getContextPath()); + this.linksEnhancer = new LinksEnhancer(this.management.getContextPath(), + this.endpoints); } @Override @@ -196,33 +200,31 @@ public class EndpointWebMvcHypermediaConfiguration { public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, - ServerHttpRequest request, ServerHttpResponse response) { - HttpServletRequest servletRequest = null; + ServerHttpRequest request, ServerHttpResponse response) { if (request instanceof ServletServerHttpRequest) { - servletRequest = ((ServletServerHttpRequest) request) - .getServletRequest(); - Object pattern = servletRequest - .getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); - if (pattern != null) { - String path = pattern.toString(); - if (isHomePage(path) || isManagementPath(path) - || isLinksPath(path)) { - ResourceSupport resource = (ResourceSupport) body; - if (isHomePage(path) && hasManagementPath()) { - String rel = this.management.getContextPath() - .substring(1); - resource.add(linkTo( - EndpointWebMvcHypermediaConfiguration.class) - .slash(this.management.getContextPath()).withRel( - rel)); - } - else { - this.linksEnhancer.addEndpointLinks(resource, ""); - } + beforeBodyWrite(body, (ServletServerHttpRequest) request); + } + return body; + } + + private void beforeBodyWrite(Object body, ServletServerHttpRequest request) { + Object pattern = request.getServletRequest().getAttribute( + HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); + if (pattern != null) { + String path = pattern.toString(); + if (isHomePage(path) || isManagementPath(path) || isLinksPath(path)) { + ResourceSupport resource = (ResourceSupport) body; + if (isHomePage(path) && hasManagementPath()) { + String rel = this.management.getContextPath().substring(1); + resource.add(linkTo( + EndpointWebMvcHypermediaConfiguration.class).slash( + this.management.getContextPath()).withRel(rel)); + } + else { + this.linksEnhancer.addEndpointLinks(resource, ""); } } } - return body; } private boolean hasManagementPath() { @@ -245,29 +247,26 @@ public class EndpointWebMvcHypermediaConfiguration { } /** - * Controller advice that adds links to the existing Actuator endpoints. By default - * all the top-level resources are enhanced with a "self" link. Those resources that - * could not be enhanced (e.g. "/env/{name}") because their values are "primitive" are - * ignored. Those that have values of type Collection (e.g. /trace) are transformed in - * to maps, and the original collection value is added with a key equal to the - * endpoint name. - * - * @author Dave Syer - * + * Controller advice that adds links to the existing Actuator endpoints. By + * default all the top-level resources are enhanced with a "self" link. Those + * resources that could not be enhanced (e.g. "/env/{name}") because their values + * are "primitive" are ignored. Those that have values of type Collection (e.g. + * /trace) are transformed in to maps, and the original collection value is added + * with a key equal to the endpoint name. */ @ControllerAdvice(assignableTypes = MvcEndpoint.class) public static class MvcEndpointAdvice implements ResponseBodyAdvice { @Autowired - ManagementServerProperties management; + private ManagementServerProperties management; @Autowired - HttpMessageConverters converters; + private HttpMessageConverters converters; private Map> converterCache = new ConcurrentHashMap>(); @Autowired - ObjectMapper mapper; + private ObjectMapper mapper; @Override public boolean supports(MethodParameter returnType, @@ -281,71 +280,71 @@ public class EndpointWebMvcHypermediaConfiguration { public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, - ServerHttpRequest request, ServerHttpResponse response) { + ServerHttpRequest request, ServerHttpResponse response) { + if (request instanceof ServletServerHttpRequest) { + return beforeBodyWrite(body, returnType, selectedContentType, + selectedConverterType, (ServletServerHttpRequest) request, + response); + } + return body; + } - if (body == null) { - // Assume it already was handled + private Object beforeBodyWrite(Object body, MethodParameter returnType, + MediaType selectedContentType, + Class> selectedConverterType, + ServletServerHttpRequest request, ServerHttpResponse response) { + if (body == null || body instanceof Resource) { + // Assume it already was handled or it already has its links return body; } - - if (body instanceof Resource) { - // Assume it already has its links - return body; - } - - @SuppressWarnings("unchecked") - HttpMessageConverter converter = (HttpMessageConverter) findConverter( + HttpMessageConverter converter = findConverter( selectedConverterType, selectedContentType); - if (converter == null) { + if (converter == null || isHypermediaDisabled(returnType)) { // Not a resource that can be enhanced with a link return body; } - if (AnnotationUtils.findAnnotation(returnType.getMethod(), - HypermediaDisabled.class) != null - || AnnotationUtils.findAnnotation(returnType.getMethod() - .getDeclaringClass(), HypermediaDisabled.class) != null) { - return body; + String path = getPath(request); + try { + converter.write(new EndpointResource(body, path), + selectedContentType, response); } - - HttpServletRequest servletRequest = null; - if (request instanceof ServletServerHttpRequest) { - servletRequest = ((ServletServerHttpRequest) request).getServletRequest(); - String path = (String) servletRequest - .getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); - if (path == null) { - path = ""; - } - try { - converter.write(new EndpointResource(body, path), - selectedContentType, response); - } - catch (IOException e) { - throw new HttpMessageNotWritableException("Cannot write response", e); - } - return null; + catch (IOException ex) { + throw new HttpMessageNotWritableException("Cannot write response", ex); } - else { - return body; - } - + return null; } - private HttpMessageConverter findConverter( + @SuppressWarnings("unchecked") + private HttpMessageConverter findConverter( Class> selectedConverterType, - MediaType mediaType) { + MediaType mediaType) { if (this.converterCache.containsKey(mediaType)) { - return this.converterCache.get(mediaType); + return (HttpMessageConverter) this.converterCache + .get(mediaType); } for (HttpMessageConverter converter : this.converters) { if (selectedConverterType.isAssignableFrom(converter.getClass()) && converter.canWrite(EndpointResource.class, mediaType)) { this.converterCache.put(mediaType, converter); - return converter; + return (HttpMessageConverter) converter; } } return null; } + private boolean isHypermediaDisabled(MethodParameter returnType) { + return AnnotationUtils.findAnnotation(returnType.getMethod(), + HypermediaDisabled.class) != null + || AnnotationUtils.findAnnotation(returnType.getMethod() + .getDeclaringClass(), HypermediaDisabled.class) != null; + } + + private String getPath(ServletServerHttpRequest request) { + String path = (String) request.getServletRequest().getAttribute( + HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); + return (path == null ? "" : path); + } + } } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/LinksEnhancer.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/LinksEnhancer.java new file mode 100644 index 0000000000..b223c62ca3 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/LinksEnhancer.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.autoconfigure; + +import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; +import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints; +import org.springframework.hateoas.ResourceSupport; +import org.springframework.util.StringUtils; + +import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; + +/** + * Adds enpoints links to {@link ResourceSupport}. + * + * @author Dave Syer + */ +class LinksEnhancer { + + private final String rootPath; + + private final MvcEndpoints endpoints; + + public LinksEnhancer(String rootPath, MvcEndpoints endpoints) { + this.rootPath = rootPath; + this.endpoints = endpoints; + } + + public void addEndpointLinks(ResourceSupport resource, String self) { + if (!resource.hasLink("self")) { + resource.add(linkTo(LinksEnhancer.class).slash(this.rootPath + self) + .withSelfRel()); + } + for (MvcEndpoint endpoint : this.endpoints.getEndpoints()) { + if (!endpoint.getPath().equals(self)) { + addEndpointLink(resource, endpoint); + } + } + } + + private void addEndpointLink(ResourceSupport resource, MvcEndpoint endpoint) { + Class type = endpoint.getEndpointType(); + type = (type == null ? Object.class : type); + String path = endpoint.getPath(); + String rel = (path.startsWith("/") ? path.substring(1) : path); + if (StringUtils.hasText(rel)) { + String fullPath = this.rootPath + endpoint.getPath(); + resource.add(linkTo(type).slash(fullPath).withRel(rel)); + } + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ManagementSecurityAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ManagementSecurityAutoConfiguration.java index 85b5698b8b..5191bb6683 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ManagementSecurityAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ManagementSecurityAutoConfiguration.java @@ -103,7 +103,7 @@ public class ManagementSecurityAutoConfiguration { @Configuration protected static class ManagementSecurityPropertiesConfiguration implements - SecurityPrerequisite { + SecurityPrerequisite { @Autowired(required = false) private SecurityProperties security; @@ -115,7 +115,7 @@ public class ManagementSecurityAutoConfiguration { public void init() { if (this.management != null && this.security != null) { this.security.getUser().getRole() - .add(this.management.getSecurity().getRole()); + .add(this.management.getSecurity().getRole()); } } @@ -124,7 +124,7 @@ public class ManagementSecurityAutoConfiguration { // Get the ignored paths in early @Order(SecurityProperties.IGNORED_ORDER + 1) private static class IgnoredPathsWebSecurityConfigurerAdapter implements - WebSecurityConfigurer { + WebSecurityConfigurer { @Autowired(required = false) private ErrorController errorController; @@ -209,7 +209,7 @@ public class ManagementSecurityAutoConfiguration { @ConditionalOnProperty(prefix = "management.security", name = "enabled", matchIfMissing = true) @Order(ManagementServerProperties.BASIC_AUTH_ORDER) protected static class ManagementWebSecurityConfigurerAdapter extends - WebSecurityConfigurerAdapter { + WebSecurityConfigurerAdapter { @Autowired private SecurityProperties security; @@ -314,17 +314,15 @@ public class ManagementSecurityAutoConfiguration { } if (this.delegate == null) { List pathMatchers = new ArrayList(); - String[] paths = !this.sensitive ? getEndpointPaths( - endpointMapping, - false) - : getEndpointPaths(endpointMapping); - for (String path : paths) { - pathMatchers.add(new AntPathRequestMatcher( - ManagementWebSecurityConfigurerAdapter.this.server + String[] paths = !this.sensitive ? getEndpointPaths(endpointMapping, + false) : getEndpointPaths(endpointMapping); + for (String path : paths) { + pathMatchers.add(new AntPathRequestMatcher( + ManagementWebSecurityConfigurerAdapter.this.server .getPath(path))); - } - this.delegate = pathMatchers.isEmpty() ? AnyRequestMatcher.INSTANCE - : new OrRequestMatcher(pathMatchers); + } + this.delegate = pathMatchers.isEmpty() ? AnyRequestMatcher.INSTANCE + : new OrRequestMatcher(pathMatchers); } return this.delegate.matches(request); } @@ -354,7 +352,8 @@ public class ManagementSecurityAutoConfiguration { paths.add(path + "/**"); // Add Spring MVC-generated additional paths paths.add(path + ".*"); - } else { + } + else { paths.add("/"); } } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/ActuatorDocsEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/ActuatorDocsEndpoint.java index 568c6d1692..2e270167bd 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/ActuatorDocsEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/ActuatorDocsEndpoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ package org.springframework.boot.actuate.endpoint.mvc; import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties; import org.springframework.boot.actuate.endpoint.Endpoint; -import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestMapping; @@ -26,45 +25,28 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** - * @author Dave Syer + * {@link MvcEndpoint} to expose actuator documentation. * + * @author Dave Syer + * @since 1.3.0 */ @ConfigurationProperties("endpoints.docs") public class ActuatorDocsEndpoint extends WebMvcConfigurerAdapter implements MvcEndpoint { + private static final String DOCS_LOCATION = "classpath:/META-INF/resources/spring-boot-actuator/docs/"; + private String path = "/docs"; private boolean sensitive; private ManagementServerProperties management; - private Curies curies = new Curies(); public Curies getCuries() { return this.curies; } - /** - * Properties of the default CurieProvider (used for adding docs links). If enabled, all - * unqualified rels will pick up a prefix and a curie template pointing to the docs endpoint. - * - */ - public static class Curies { - /** - * Enable the curie generation (off by default). - */ - private boolean enabled = false; - - public boolean isEnabled() { - return this.enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - } - public ActuatorDocsEndpoint(ManagementServerProperties management) { this.management = management; } @@ -82,8 +64,7 @@ public class ActuatorDocsEndpoint extends WebMvcConfigurerAdapter implements Mvc @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(this.management.getContextPath() + this.path + "/**") - .addResourceLocations( - "classpath:/META-INF/resources/spring-boot-actuator/docs/"); + .addResourceLocations(DOCS_LOCATION); } public void setPath(String path) { @@ -109,4 +90,26 @@ public class ActuatorDocsEndpoint extends WebMvcConfigurerAdapter implements Mvc return null; } + /** + * Properties of the default CurieProvider (used for adding docs links). If enabled, + * all unqualified rels will pick up a prefix and a curie template pointing to the + * docs endpoint. + */ + public static class Curies { + + /** + * Enable the curie generation (off by default). + */ + private boolean enabled = false; + + public boolean isEnabled() { + return this.enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + } + } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EnvironmentMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EnvironmentMvcEndpoint.java index 655059cf5b..e149f2f5cc 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EnvironmentMvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EnvironmentMvcEndpoint.java @@ -38,7 +38,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; * @author Andy Wilkinson */ public class EnvironmentMvcEndpoint extends EndpointMvcAdapter implements -EnvironmentAware { + EnvironmentAware { private Environment environment; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HalBrowserEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HalBrowserEndpoint.java index 96aafbb823..6f0add7db9 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HalBrowserEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HalBrowserEndpoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,14 +25,19 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** - * @author Dave Syer + * {@link MvcEndpoint} to support the Spring Data HAL browser. * + * @author Dave Syer + * @since 1.3.0 */ @ConfigurationProperties("endpoints.hal") public class HalBrowserEndpoint extends WebMvcConfigurerAdapter implements MvcEndpoint { private static final String HAL_BROWSER_VERSION = "b7669f1-1"; + private static final String HAL_BROWSER_LOCATION = "classpath:/META-INF/resources/webjars/hal-browser/" + + HAL_BROWSER_VERSION + "/"; + private String path = ""; private ManagementServerProperties management; @@ -58,16 +63,11 @@ public class HalBrowserEndpoint extends WebMvcConfigurerAdapter implements MvcEn @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { - // Make sure the root path is not cached otherwise the browser won't come back for - // the JSON + // Make sure the root path is not cached so the browser comes back for the JSON registry.addResourceHandler(this.management.getContextPath() + this.path + "/") - .addResourceLocations( - "classpath:/META-INF/resources/webjars/hal-browser/" - + HAL_BROWSER_VERSION + "/").setCachePeriod(0); + .addResourceLocations(HAL_BROWSER_LOCATION).setCachePeriod(0); registry.addResourceHandler(this.management.getContextPath() + this.path + "/**") - .addResourceLocations( - "classpath:/META-INF/resources/webjars/hal-browser/" - + HAL_BROWSER_VERSION + "/"); + .addResourceLocations(HAL_BROWSER_LOCATION); } public void setPath(String path) { diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HypermediaDisabled.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HypermediaDisabled.java index 100481d86a..032a531b23 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HypermediaDisabled.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HypermediaDisabled.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,11 +22,16 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.springframework.web.bind.annotation.RequestMapping; + /** - * @author Dave Syer + * Annotation to that {@link MvcEndpoint} class or {@link RequestMapping} method should't + * generate a hypermedia response. * + * @author Dave Syer + * @since 1.3.0 */ -@Target({ElementType.TYPE, ElementType.METHOD}) +@Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface HypermediaDisabled { diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpoint.java index fa16def8a5..1f708f68e3 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpoint.java @@ -47,7 +47,7 @@ import org.springframework.web.util.UrlPathHelper; @ConfigurationProperties(prefix = "endpoints.jolokia", ignoreUnknownFields = false) @HypermediaDisabled public class JolokiaMvcEndpoint implements MvcEndpoint, InitializingBean, -ApplicationContextAware, ServletContextAware { + ApplicationContextAware, ServletContextAware { /** * Endpoint URL path. diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/LinksEnhancer.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/LinksEnhancer.java deleted file mode 100644 index 6e96af9756..0000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/LinksEnhancer.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.endpoint.mvc; - -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; - -import org.springframework.hateoas.ResourceSupport; -import org.springframework.util.StringUtils; - -/** - * @author Dave Syer - * - */ -public class LinksEnhancer { - - private MvcEndpoints endpoints; - - private String rootPath; - - public LinksEnhancer(MvcEndpoints endpoints, String rootPath) { - this.endpoints = endpoints; - this.rootPath = rootPath; - } - - public void addEndpointLinks(ResourceSupport resource, String self) { - if (!resource.hasLink("self")) { - resource.add(linkTo(LinksEnhancer.class).slash( - this.rootPath + self).withSelfRel()); - } - for (MvcEndpoint endpoint : this.endpoints.getEndpoints()) { - if (endpoint.getPath().equals(self)) { - continue; - } - Class type = endpoint.getEndpointType(); - if (type == null) { - type = Object.class; - } - String path = endpoint.getPath(); - String rel = path.startsWith("/") ? path.substring(1) : path; - if (StringUtils.hasText(rel)) { - resource.add(linkTo(type).slash(this.rootPath + endpoint.getPath()) - .withRel(rel)); - } - } - } - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/LinksMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/LinksMvcEndpoint.java index 7466a9ee2f..baab0c22be 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/LinksMvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/LinksMvcEndpoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2013-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,8 +24,10 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; /** - * @author Dave Syer + * {@link MvcEndpoint} to add hypermedia links. * + * @author Dave Syer + * @since 1.3.0 */ @ConfigurationProperties("endpoints.links") public class LinksMvcEndpoint implements MvcEndpoint { @@ -37,7 +39,7 @@ public class LinksMvcEndpoint implements MvcEndpoint { this.path = defaultPath; } - @RequestMapping(value = { "/", "" }, produces=MediaType.APPLICATION_JSON_VALUE) + @RequestMapping(value = { "/", "" }, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody public ResourceSupport links() { ResourceSupport resource = new ResourceSupport(); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/BrowserPathHypermediaIntegrationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/BrowserPathHypermediaIntegrationTests.java index 668886bf6b..af92911d15 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/BrowserPathHypermediaIntegrationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/BrowserPathHypermediaIntegrationTests.java @@ -1,9 +1,20 @@ -package org.springframework.boot.actuate.autoconfigure; +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import static org.junit.Assert.assertEquals; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +package org.springframework.boot.actuate.autoconfigure; import org.junit.Before; import org.junit.Test; @@ -24,6 +35,11 @@ import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import static org.junit.Assert.assertEquals; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = SpringBootHypermediaApplication.class) @WebAppConfiguration @@ -55,8 +71,8 @@ public class BrowserPathHypermediaIntegrationTests { @Test public void redirect() throws Exception { this.mockMvc.perform(get("/hal").accept(MediaType.TEXT_HTML)) - .andExpect(status().isFound()) - .andExpect(header().string("location", "/hal/#")); + .andExpect(status().isFound()) + .andExpect(header().string("location", "/hal/#")); } @MinimalActuatorHypermediaApplication @@ -66,6 +82,7 @@ public class BrowserPathHypermediaIntegrationTests { public static void main(String[] args) { SpringApplication.run(SpringBootHypermediaApplication.class, args); } + } } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ContextPathHypermediaIntegrationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ContextPathHypermediaIntegrationTests.java index 78eae21400..341e4d7990 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ContextPathHypermediaIntegrationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ContextPathHypermediaIntegrationTests.java @@ -1,9 +1,20 @@ -package org.springframework.boot.actuate.autoconfigure; +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +package org.springframework.boot.actuate.autoconfigure; import org.junit.Before; import org.junit.Test; @@ -26,6 +37,11 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.WebApplicationContext; +import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = SpringBootHypermediaApplication.class) @WebAppConfiguration @@ -49,24 +65,24 @@ public class ContextPathHypermediaIntegrationTests { @Test public void home() throws Exception { this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()).andExpect(jsonPath("$._links").exists()); + .andExpect(status().isOk()).andExpect(jsonPath("$._links").exists()); } @Test public void links() throws Exception { this.mockMvc.perform(get("/admin").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()).andExpect(jsonPath("$._links").exists()); + .andExpect(status().isOk()).andExpect(jsonPath("$._links").exists()); } @Test public void trace() throws Exception { this.mockMvc - .perform(get("/admin/trace").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect( - jsonPath("$._links.self.href").value( - "http://localhost/admin/trace")) - .andExpect(jsonPath("$.content").isArray()); + .perform(get("/admin/trace").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$._links.self.href").value( + "http://localhost/admin/trace")) + .andExpect(jsonPath("$.content").isArray()); } @Test @@ -76,11 +92,11 @@ public class ContextPathHypermediaIntegrationTests { path = path.startsWith("/") ? path.substring(1) : path; path = path.length() > 0 ? path : "self"; this.mockMvc - .perform(get("/admin").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect( - jsonPath("$._links.%s.href", path).value( - "http://localhost/admin" + endpoint.getPath())); + .perform(get("/admin").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$._links.%s.href", path).value( + "http://localhost/admin" + endpoint.getPath())); } } @@ -98,8 +114,9 @@ public class ContextPathHypermediaIntegrationTests { public static void main(String[] args) { new SpringApplicationBuilder(SpringBootHypermediaApplication.class) - .properties("management.contextPath:/admin").run(args); + .properties("management.contextPath:/admin").run(args); } + } } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/CustomHomepageHypermediaIntegrationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/CustomHomepageHypermediaIntegrationTests.java index 674c03d0b9..a91b147816 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/CustomHomepageHypermediaIntegrationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/CustomHomepageHypermediaIntegrationTests.java @@ -1,9 +1,20 @@ -package org.springframework.boot.actuate.autoconfigure; +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +package org.springframework.boot.actuate.autoconfigure; import org.junit.Before; import org.junit.Test; @@ -25,6 +36,11 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.WebApplicationContext; +import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = SpringBootHypermediaApplication.class) @WebAppConfiguration @@ -47,7 +63,7 @@ public class CustomHomepageHypermediaIntegrationTests { @Test public void links() throws Exception { this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()).andExpect(jsonPath("$._links").exists()); + .andExpect(status().isOk()).andExpect(jsonPath("$._links").exists()); } @Test @@ -56,8 +72,8 @@ public class CustomHomepageHypermediaIntegrationTests { String path = endpoint.getPath(); path = path.startsWith("/") ? path.substring(1) : path; this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$._links.%s.href", path).exists()); + .andExpect(status().isOk()) + .andExpect(jsonPath("$._links.%s.href", path).exists()); } } @@ -68,13 +84,15 @@ public class CustomHomepageHypermediaIntegrationTests { @RequestMapping("") public ResourceSupport home() { ResourceSupport resource = new ResourceSupport(); - resource.add(linkTo(SpringBootHypermediaApplication.class).slash("/").withSelfRel()); + resource.add(linkTo(SpringBootHypermediaApplication.class).slash("/") + .withSelfRel()); return resource; } public static void main(String[] args) { SpringApplication.run(SpringBootHypermediaApplication.class, args); } + } } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMvcIntegrationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMvcIntegrationTests.java index 4ebb3e1e73..f10e9b2b9a 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMvcIntegrationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMvcIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +16,6 @@ package org.springframework.boot.actuate.autoconfigure; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -63,6 +60,9 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + /** * Integration tests for MVC {@link Endpoint}s. * @@ -94,19 +94,19 @@ public class EndpointMvcIntegrationTests { @Retention(RetentionPolicy.RUNTIME) @Documented @Import({ EmbeddedServletContainerAutoConfiguration.class, - ServerPropertiesAutoConfiguration.class, - DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class, - JacksonAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, - ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) + ServerPropertiesAutoConfiguration.class, + DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class, + JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, + ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) protected static @interface MinimalWebConfiguration { } @Configuration @MinimalWebConfiguration - @Import({ ManagementServerPropertiesAutoConfiguration.class, JacksonAutoConfiguration.class, - EndpointAutoConfiguration.class, EndpointWebMvcAutoConfiguration.class }) + @Import({ ManagementServerPropertiesAutoConfiguration.class, + JacksonAutoConfiguration.class, EndpointAutoConfiguration.class, + EndpointWebMvcAutoConfiguration.class }) @RestController protected static class Application { diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfigurationTests.java index cb20ac6e8b..a1f202009f 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfigurationTests.java @@ -16,18 +16,6 @@ package org.springframework.boot.actuate.autoconfigure; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - import java.io.FileNotFoundException; import java.net.SocketException; import java.net.URI; @@ -84,6 +72,18 @@ import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + /** * Tests for {@link EndpointWebMvcAutoConfiguration}. * @@ -228,8 +228,7 @@ public class EndpointWebMvcAutoConfigurationTests { this.applicationContext.register(RootConfig.class, EndpointConfig.class, ServerPortConfig.class, PropertyPlaceholderAutoConfiguration.class, ManagementServerPropertiesAutoConfiguration.class, - ServerPropertiesAutoConfiguration.class, - JacksonAutoConfiguration.class, + ServerPropertiesAutoConfiguration.class, JacksonAutoConfiguration.class, EmbeddedServletContainerAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class, @@ -246,7 +245,7 @@ public class EndpointWebMvcAutoConfigurationTests { this.applicationContext.register(RootConfig.class, BaseConfiguration.class, ServerPortConfig.class, EndpointWebMvcAutoConfiguration.class); new ServerPortInfoApplicationContextInitializer() - .initialize(this.applicationContext); + .initialize(this.applicationContext); this.applicationContext.refresh(); Integer localServerPort = this.applicationContext.getEnvironment().getProperty( "local.server.port", Integer.class); @@ -262,7 +261,7 @@ public class EndpointWebMvcAutoConfigurationTests { @Test public void portPropertiesOnDifferentPort() throws Exception { new ServerPortInfoApplicationContextInitializer() - .initialize(this.applicationContext); + .initialize(this.applicationContext); this.applicationContext.register(RootConfig.class, DifferentPortConfig.class, BaseConfiguration.class, EndpointWebMvcAutoConfiguration.class, ErrorMvcAutoConfiguration.class); @@ -423,13 +422,12 @@ public class EndpointWebMvcAutoConfigurationTests { @Configuration @Import({ PropertyPlaceholderAutoConfiguration.class, - EmbeddedServletContainerAutoConfiguration.class, - JacksonAutoConfiguration.class, - EndpointAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, - DispatcherServletAutoConfiguration.class, - ManagementServerPropertiesAutoConfiguration.class, - ServerPropertiesAutoConfiguration.class, WebMvcAutoConfiguration.class }) + EmbeddedServletContainerAutoConfiguration.class, + JacksonAutoConfiguration.class, EndpointAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, + DispatcherServletAutoConfiguration.class, + ManagementServerPropertiesAutoConfiguration.class, + ServerPropertiesAutoConfiguration.class, WebMvcAutoConfiguration.class }) protected static class BaseConfiguration { } @@ -587,7 +585,7 @@ public class EndpointWebMvcAutoConfigurationTests { } private static class GrabManagementPort implements - ApplicationListener { + ApplicationListener { private ApplicationContext rootContext; diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthMvcEndpointAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthMvcEndpointAutoConfigurationTests.java index 2aaeaa6d98..ec46c38a6d 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthMvcEndpointAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthMvcEndpointAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,6 @@ package org.springframework.boot.actuate.autoconfigure; -import static org.junit.Assert.assertEquals; - import org.junit.After; import org.junit.Test; import org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint; @@ -33,6 +31,8 @@ import org.springframework.mock.web.MockServletContext; import org.springframework.stereotype.Component; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import static org.junit.Assert.assertEquals; + /** * Tests for {@link EndpointWebMvcAutoConfiguration} of the {@link HealthMvcEndpoint}. * diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ManagementSecurityAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ManagementSecurityAutoConfigurationTests.java index f42231ef27..70a0e89c3c 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ManagementSecurityAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ManagementSecurityAutoConfigurationTests.java @@ -16,13 +16,6 @@ package org.springframework.boot.actuate.autoconfigure; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.hasSize; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; - import javax.servlet.Filter; import org.hamcrest.Matchers; @@ -60,6 +53,13 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.util.StringUtils; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.hasSize; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + /** * Tests for {@link ManagementSecurityAutoConfiguration}. * @@ -111,8 +111,7 @@ public class ManagementSecurityAutoConfigurationTests { this.context = new AnnotationConfigWebApplicationContext(); this.context.setServletContext(new MockServletContext()); this.context.register(EndpointAutoConfiguration.class, - EndpointWebMvcAutoConfiguration.class, - JacksonAutoConfiguration.class, + EndpointWebMvcAutoConfiguration.class, JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, ManagementServerPropertiesAutoConfiguration.class, SecurityAutoConfiguration.class, @@ -122,7 +121,7 @@ public class ManagementSecurityAutoConfigurationTests { UserDetails user = getUser(); assertTrue(user.getAuthorities().containsAll( AuthorityUtils - .commaSeparatedStringToAuthorityList("ROLE_USER,ROLE_ADMIN"))); + .commaSeparatedStringToAuthorityList("ROLE_USER,ROLE_ADMIN"))); } private UserDetails getUser() { @@ -157,8 +156,8 @@ public class ManagementSecurityAutoConfigurationTests { this.context = new AnnotationConfigWebApplicationContext(); this.context.setServletContext(new MockServletContext()); this.context.register(HttpMessageConvertersAutoConfiguration.class, - JacksonAutoConfiguration.class, - EndpointAutoConfiguration.class, EndpointWebMvcAutoConfiguration.class, + JacksonAutoConfiguration.class, EndpointAutoConfiguration.class, + EndpointWebMvcAutoConfiguration.class, ManagementServerPropertiesAutoConfiguration.class, SecurityAutoConfiguration.class, ManagementSecurityAutoConfiguration.class, @@ -205,15 +204,16 @@ public class ManagementSecurityAutoConfigurationTests { public void realmSameForManagement() throws Exception { this.context = new AnnotationConfigWebApplicationContext(); this.context.setServletContext(new MockServletContext()); - this.context.register(AuthenticationConfig.class, - SecurityAutoConfiguration.class, - ManagementSecurityAutoConfiguration.class, - JacksonAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, - EndpointAutoConfiguration.class, EndpointWebMvcAutoConfiguration.class, - ManagementServerPropertiesAutoConfiguration.class, - WebMvcAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class); + this.context + .register(AuthenticationConfig.class, SecurityAutoConfiguration.class, + ManagementSecurityAutoConfiguration.class, + JacksonAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, + EndpointAutoConfiguration.class, + EndpointWebMvcAutoConfiguration.class, + ManagementServerPropertiesAutoConfiguration.class, + WebMvcAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); this.context.refresh(); Filter filter = this.context.getBean("springSecurityFilterChain", Filter.class); @@ -222,8 +222,8 @@ public class ManagementSecurityAutoConfigurationTests { // no user (Main) mockMvc.perform(MockMvcRequestBuilders.get("/home")) - .andExpect(MockMvcResultMatchers.status().isUnauthorized()) - .andExpect(springAuthenticateRealmHeader()); + .andExpect(MockMvcResultMatchers.status().isUnauthorized()) + .andExpect(springAuthenticateRealmHeader()); // invalid user (Main) mockMvc.perform( @@ -233,8 +233,8 @@ public class ManagementSecurityAutoConfigurationTests { // no user (Management) mockMvc.perform(MockMvcRequestBuilders.get("/beans")) - .andExpect(MockMvcResultMatchers.status().isUnauthorized()) - .andExpect(springAuthenticateRealmHeader()); + .andExpect(MockMvcResultMatchers.status().isUnauthorized()) + .andExpect(springAuthenticateRealmHeader()); // invalid user (Management) mockMvc.perform( @@ -254,7 +254,7 @@ public class ManagementSecurityAutoConfigurationTests { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("user").password("password") - .roles("USER"); + .roles("USER"); } } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MinimalActuatorHypermediaApplication.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MinimalActuatorHypermediaApplication.java index 00b92c8a4c..b286e04b04 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MinimalActuatorHypermediaApplication.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MinimalActuatorHypermediaApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,20 +36,19 @@ import org.springframework.context.annotation.Import; /** * @author Dave Syer - * */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration @Import({ ServerPropertiesAutoConfiguration.class, - ManagementServerPropertiesAutoConfiguration.class, - EmbeddedServletContainerAutoConfiguration.class, - DispatcherServletAutoConfiguration.class, JacksonAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, WebMvcAutoConfiguration.class, - HypermediaAutoConfiguration.class, EndpointAutoConfiguration.class, - EndpointWebMvcAutoConfiguration.class, ErrorMvcAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class }) + ManagementServerPropertiesAutoConfiguration.class, + EmbeddedServletContainerAutoConfiguration.class, + DispatcherServletAutoConfiguration.class, JacksonAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, WebMvcAutoConfiguration.class, + HypermediaAutoConfiguration.class, EndpointAutoConfiguration.class, + EndpointWebMvcAutoConfiguration.class, ErrorMvcAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class }) public @interface MinimalActuatorHypermediaApplication { } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ServerContextPathHypermediaIntegrationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ServerContextPathHypermediaIntegrationTests.java index 876f97ad0e..a52675aa7d 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ServerContextPathHypermediaIntegrationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ServerContextPathHypermediaIntegrationTests.java @@ -1,8 +1,20 @@ -package org.springframework.boot.actuate.autoconfigure; +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; +package org.springframework.boot.actuate.autoconfigure; import java.util.Arrays; @@ -27,6 +39,10 @@ import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; + @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = SpringBootHypermediaApplication.class) @WebAppConfiguration @@ -57,8 +73,7 @@ public class ServerContextPathHypermediaIntegrationTests { "http://localhost:" + this.port + "/spring/", HttpMethod.GET, new HttpEntity(null, headers), String.class); assertEquals(HttpStatus.OK, entity.getStatusCode()); - assertTrue("Wrong body: " + entity.getBody(), - entity.getBody().contains(" 0 ? path : "/"; this.mockMvc - .perform(get(path).accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect( - jsonPath("$._links.self.href").value( - "http://localhost" + endpoint.getPath())); + .perform(get(path).accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$._links.self.href").value( + "http://localhost" + endpoint.getPath())); } } @@ -110,6 +126,7 @@ public class VanillaHypermediaIntegrationTests { public static void main(String[] args) { SpringApplication.run(SpringBootHypermediaApplication.class, args); } + } } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/EnvironmentMvcEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/EnvironmentMvcEndpointTests.java index e3db7deb29..c7be6db09f 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/EnvironmentMvcEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/EnvironmentMvcEndpointTests.java @@ -16,12 +16,6 @@ package org.springframework.boot.actuate.endpoint.mvc; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalToIgnoringCase; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -45,6 +39,12 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalToIgnoringCase; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + /** * Tests for {@link EnvironmentMvcEndpoint} * @@ -72,13 +72,13 @@ public class EnvironmentMvcEndpointTests { @Test public void home() throws Exception { this.mvc.perform(get("/env")).andExpect(status().isOk()) - .andExpect(content().string(containsString("systemProperties"))); + .andExpect(content().string(containsString("systemProperties"))); } @Test public void sub() throws Exception { this.mvc.perform(get("/env/foo")).andExpect(status().isOk()) - .andExpect(content().string(equalToIgnoringCase("bar"))); + .andExpect(content().string(equalToIgnoringCase("bar"))); } @Test @@ -90,15 +90,14 @@ public class EnvironmentMvcEndpointTests { @Test public void regex() throws Exception { this.mvc.perform(get("/env/foo.*")).andExpect(status().isOk()) - .andExpect(content().string(containsString("\"foo\":\"bar\""))) - .andExpect(content().string(containsString("\"fool\":\"baz\""))); + .andExpect(content().string(containsString("\"foo\":\"bar\""))) + .andExpect(content().string(containsString("\"fool\":\"baz\""))); } @Import({ JacksonAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, - WebMvcAutoConfiguration.class, - EndpointWebMvcAutoConfiguration.class, - ManagementServerPropertiesAutoConfiguration.class }) + HttpMessageConvertersAutoConfiguration.class, WebMvcAutoConfiguration.class, + EndpointWebMvcAutoConfiguration.class, + ManagementServerPropertiesAutoConfiguration.class }) @Configuration public static class TestConfiguration { diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpointContextPathTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpointContextPathTests.java index 9b338faabf..b2e9b9dc21 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpointContextPathTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpointContextPathTests.java @@ -16,11 +16,6 @@ package org.springframework.boot.actuate.endpoint.mvc; -import static org.hamcrest.Matchers.containsString; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -46,6 +41,11 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import static org.hamcrest.Matchers.containsString; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + /** * @author Christian Dupuis * @author Dave Syer @@ -73,22 +73,22 @@ public class JolokiaMvcEndpointContextPathTests { @Test public void read() throws Exception { this.mvc.perform(get("/admin/jolokia/read/java.lang:type=Memory")) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("NonHeapMemoryUsage"))); + .andExpect(status().isOk()) + .andExpect(content().string(containsString("NonHeapMemoryUsage"))); } @Configuration @EnableConfigurationProperties @EnableWebMvc @Import({ JacksonAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, - EndpointWebMvcAutoConfiguration.class, JolokiaAutoConfiguration.class, - ManagementServerPropertiesAutoConfiguration.class }) + HttpMessageConvertersAutoConfiguration.class, + EndpointWebMvcAutoConfiguration.class, JolokiaAutoConfiguration.class, + ManagementServerPropertiesAutoConfiguration.class }) public static class Config { } public static class ContextPathListener implements - ApplicationContextInitializer { + ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext context) { EnvironmentTestUtils.addEnvironment(context, "management.contextPath:/admin"); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpointTests.java index 3df45ee534..0a3cdd533a 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpointTests.java @@ -16,14 +16,6 @@ package org.springframework.boot.actuate.endpoint.mvc; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.instanceOf; -import static org.junit.Assert.assertThat; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - import java.util.Set; import org.hamcrest.Matcher; @@ -50,6 +42,14 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.Assert.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + /** * Tests for {@link JolokiaMvcEndpoint} * @@ -86,30 +86,30 @@ public class JolokiaMvcEndpointTests { @Test public void search() throws Exception { this.mvc.perform(get("/jolokia/search/java.lang:*")).andExpect(status().isOk()) - .andExpect(content().string(containsString("GarbageCollector"))); + .andExpect(content().string(containsString("GarbageCollector"))); } @Test public void read() throws Exception { this.mvc.perform(get("/jolokia/read/java.lang:type=Memory")) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("NonHeapMemoryUsage"))); + .andExpect(status().isOk()) + .andExpect(content().string(containsString("NonHeapMemoryUsage"))); } @Test public void list() throws Exception { this.mvc.perform(get("/jolokia/list/java.lang/type=Memory/attr")) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("NonHeapMemoryUsage"))); + .andExpect(status().isOk()) + .andExpect(content().string(containsString("NonHeapMemoryUsage"))); } @Configuration @EnableConfigurationProperties @EnableWebMvc @Import({ JacksonAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, - EndpointWebMvcAutoConfiguration.class, JolokiaAutoConfiguration.class, - ManagementServerPropertiesAutoConfiguration.class }) + HttpMessageConvertersAutoConfiguration.class, + EndpointWebMvcAutoConfiguration.class, JolokiaAutoConfiguration.class, + ManagementServerPropertiesAutoConfiguration.class }) public static class Config { } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MetricsMvcEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MetricsMvcEndpointTests.java index 55a51ceb1f..df38788d58 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MetricsMvcEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MetricsMvcEndpointTests.java @@ -16,12 +16,6 @@ package org.springframework.boot.actuate.endpoint.mvc; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -49,6 +43,12 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + /** * Tests for {@link MetricsMvcEndpoint} * @@ -74,7 +74,7 @@ public class MetricsMvcEndpointTests { @Test public void home() throws Exception { this.mvc.perform(get("/metrics")).andExpect(status().isOk()) - .andExpect(content().string(containsString("\"foo\":1"))); + .andExpect(content().string(containsString("\"foo\":1"))); } @Test @@ -86,7 +86,7 @@ public class MetricsMvcEndpointTests { @Test public void specificMetric() throws Exception { this.mvc.perform(get("/metrics/foo")).andExpect(status().isOk()) - .andExpect(content().string(equalTo("1"))); + .andExpect(content().string(equalTo("1"))); } @Test @@ -104,35 +104,34 @@ public class MetricsMvcEndpointTests { public void regexAll() throws Exception { String expected = "\"foo\":1,\"group1.a\":1,\"group1.b\":1,\"group2.a\":1,\"group2_a\":1"; this.mvc.perform(get("/metrics/.*")).andExpect(status().isOk()) - .andExpect(content().string(containsString(expected))); + .andExpect(content().string(containsString(expected))); } @Test public void regexGroupDot() throws Exception { String expected = "\"group1.a\":1,\"group1.b\":1,\"group2.a\":1"; this.mvc.perform(get("/metrics/group[0-9]+\\..*")).andExpect(status().isOk()) - .andExpect(content().string(containsString(expected))); + .andExpect(content().string(containsString(expected))); } @Test public void regexGroup1() throws Exception { String expected = "\"group1.a\":1,\"group1.b\":1"; this.mvc.perform(get("/metrics/group1\\..*")).andExpect(status().isOk()) - .andExpect(content().string(containsString(expected))); + .andExpect(content().string(containsString(expected))); } @Test public void specificMetricWithDot() throws Exception { this.mvc.perform(get("/metrics/group2.a")).andExpect(status().isOk()) - .andExpect(content().string(containsString("1"))); + .andExpect(content().string(containsString("1"))); } @Import({ JacksonAutoConfiguration.class, - HttpMessageConvertersAutoConfiguration.class, - EndpointWebMvcAutoConfiguration.class, - WebMvcAutoConfiguration.class, - ManagementServerPropertiesAutoConfiguration.class }) + HttpMessageConvertersAutoConfiguration.class, + EndpointWebMvcAutoConfiguration.class, WebMvcAutoConfiguration.class, + ManagementServerPropertiesAutoConfiguration.class }) @Configuration public static class TestConfiguration { diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointCorsIntegrationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointCorsIntegrationTests.java index 29dd74b717..dec7065143 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointCorsIntegrationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointCorsIntegrationTests.java @@ -16,10 +16,6 @@ package org.springframework.boot.actuate.endpoint.mvc; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - import org.junit.Before; import org.junit.Test; import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration; @@ -38,6 +34,10 @@ import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + /** * Integration tests for the actuator endpoints' CORS support * @@ -51,7 +51,8 @@ public class MvcEndpointCorsIntegrationTests { public void createContext() { this.context = new AnnotationConfigWebApplicationContext(); this.context.setServletContext(new MockServletContext()); - this.context.register(JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, + this.context.register(JacksonAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class, EndpointWebMvcAutoConfiguration.class, ManagementServerPropertiesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, @@ -63,7 +64,7 @@ public class MvcEndpointCorsIntegrationTests { createMockMvc().perform( options("/beans").header("Origin", "foo.example.com").header( HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")).andExpect( - header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); } @Test @@ -73,7 +74,7 @@ public class MvcEndpointCorsIntegrationTests { createMockMvc().perform( options("/beans").header("Origin", "bar.example.com").header( HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")).andExpect( - status().isForbidden()); + status().isForbidden()); performAcceptedCorsRequest(); } @@ -100,8 +101,8 @@ public class MvcEndpointCorsIntegrationTests { "endpoints.cors.allowed-origins:foo.example.com"); createMockMvc().perform( options("/beans").header("Origin", "foo.example.com") - .header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET") - .header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha")) + .header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET") + .header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha")) .andExpect(status().isForbidden()); } @@ -111,15 +112,15 @@ public class MvcEndpointCorsIntegrationTests { "endpoints.cors.allowed-origins:foo.example.com", "endpoints.cors.allowed-headers:Alpha,Bravo"); createMockMvc() - .perform( - options("/beans") - .header("Origin", "foo.example.com") - .header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET") - .header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, - "Alpha")) - .andExpect(status().isOk()) - .andExpect( - header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Alpha")); + .perform( + options("/beans") + .header("Origin", "foo.example.com") + .header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET") + .header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, + "Alpha")) + .andExpect(status().isOk()) + .andExpect( + header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Alpha")); } @Test @@ -129,7 +130,7 @@ public class MvcEndpointCorsIntegrationTests { createMockMvc().perform( options("/health").header(HttpHeaders.ORIGIN, "foo.example.com").header( HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "HEAD")).andExpect( - status().isForbidden()); + status().isForbidden()); } @Test @@ -138,10 +139,10 @@ public class MvcEndpointCorsIntegrationTests { "endpoints.cors.allowed-origins:foo.example.com", "endpoints.cors.allowed-methods:GET,HEAD"); createMockMvc() - .perform( - options("/health") - .header(HttpHeaders.ORIGIN, "foo.example.com") - .header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "HEAD")) + .perform( + options("/health") + .header(HttpHeaders.ORIGIN, "foo.example.com") + .header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "HEAD")) .andExpect(status().isOk()) .andExpect( header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, @@ -173,7 +174,7 @@ public class MvcEndpointCorsIntegrationTests { createMockMvc().perform( options("/jolokia").header("Origin", "bar.example.com").header( HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")).andExpect( - status().isForbidden()); + status().isForbidden()); performAcceptedCorsRequest("/jolokia"); } @@ -190,10 +191,10 @@ public class MvcEndpointCorsIntegrationTests { return createMockMvc() .perform( options(url).header(HttpHeaders.ORIGIN, "foo.example.com") - .header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")) - .andExpect( - header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, - "foo.example.com")).andExpect(status().isOk()); + .header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")) + .andExpect( + header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, + "foo.example.com")).andExpect(status().isOk()); } } diff --git a/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc b/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc index 9aabe02583..7673950d4e 100644 --- a/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc @@ -150,30 +150,33 @@ For example, the following will disable _all_ endpoints except for `info`: endpoints.info.enabled=true ---- + + [[production-ready-endpoint-hypermedia]] === Hypermedia for MVC Endpoints If http://projects.spring.io/spring-hateoas[Spring HATEOAS] is on the classpath (e.g. -through the `spring-boot-starter-hateoas` or if you are using +through the `spring-boot-starter-hateoas` or if you are using http://projects.spring.io/spring-data-rest[Spring Data REST]) then the HTTP endpoints from the Actuator are enhanced with hypermedia links, and a "discovery page" is added with links to all the endpoints. The "discovery page" is actually an endpoint itself, -so it can be disabled along with the rest of the hypermedia by setting -`endpoints.links.enabled=false`. If it is not explicitly disabled the links +so it can be disabled along with the rest of the hypermedia by setting +`endpoints.links.enabled=false`. If it is not explicitly disabled the links endpoint renders a JSON object with a link for each other endpoint, and the default -path is the same as the `management.contentPath` (so "/" by default). +path is the same as the `management.contentPath` (so "`/`" by default). -NOTE: if there is a static home page ("index.html") in your application and the links -endpoint is registered with its default path ("/") then content negotiation will kick in +NOTE: if there is a static home page ("`index.html`") in your application and the links +endpoint is registered with its default path ("`/`") then content negotiation will kick in to determine which content is shown to a client that requests the home page (the links will show only if the client accepts `application/json`). If the https://github.com/mikekelly/hal-browser[HAL Browser] is on the classpath via its webjar (`org.webjars:hal-browser`), or via the `spring-data-hal-browser` then -the default home page for HTML clients will be the HAL Browser. This is also exposed via an -endpoint ("hal") so it can be disabled and have its path explicitly configured like +the default home page for HTML clients will be the HAL Browser. This is also exposed via +an endpoint ("`hal`") so it can be disabled and have its path explicitly configured like the other endpoints. + [[production-ready-customizing-endpoints-programmatically]] === Adding Custom Endpoints If you add a `@Bean` of type `Endpoint` then it will automatically be exposed over JMX and diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-gson/pom.xml b/spring-boot-samples/spring-boot-sample-hypermedia-gson/pom.xml index e8f6fc2c20..5bb0317371 100644 --- a/spring-boot-samples/spring-boot-sample-hypermedia-gson/pom.xml +++ b/spring-boot-samples/spring-boot-sample-hypermedia-gson/pom.xml @@ -2,24 +2,19 @@ 4.0.0 - - spring-boot-sample-hypermedia-gson - jar - - spring-boot-sample-hypermedia-gson - Demo project for Spring Boot - + org.springframework.boot spring-boot-samples 1.3.0.BUILD-SNAPSHOT - + spring-boot-sample-hypermedia-gson + Spring Boot Hypermedia GSON Sample + Spring Boot Hypermedia GSON Sample - UTF-8 + ${basedir}/../.. 1.7 - org.springframework.boot @@ -37,11 +32,6 @@ com.google.code.gson gson - - org.springframework.boot - spring-boot-devtools - true - org.springframework.boot spring-boot-starter-test @@ -53,7 +43,6 @@ test - @@ -62,5 +51,4 @@ - diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-gson/src/main/java/demo/SpringBootHypermediaApplication.java b/spring-boot-samples/spring-boot-sample-hypermedia-gson/src/main/java/demo/SpringBootHypermediaApplication.java deleted file mode 100644 index 954faed6f9..0000000000 --- a/spring-boot-samples/spring-boot-sample-hypermedia-gson/src/main/java/demo/SpringBootHypermediaApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package demo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringBootHypermediaApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringBootHypermediaApplication.class, args); - } -} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-gson/src/main/java/sample/hypermedia/gson/SampleHypermediaGsonApplication.java b/spring-boot-samples/spring-boot-sample-hypermedia-gson/src/main/java/sample/hypermedia/gson/SampleHypermediaGsonApplication.java new file mode 100644 index 0000000000..eff80ee9af --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hypermedia-gson/src/main/java/sample/hypermedia/gson/SampleHypermediaGsonApplication.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.hypermedia.gson; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SampleHypermediaGsonApplication { + + public static void main(String[] args) { + SpringApplication.run(SampleHypermediaGsonApplication.class, args); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-gson/src/test/java/demo/SpringBootHypermediaApplicationTests.java b/spring-boot-samples/spring-boot-sample-hypermedia-gson/src/test/java/demo/SpringBootHypermediaApplicationTests.java deleted file mode 100644 index 54e46efb31..0000000000 --- a/spring-boot-samples/spring-boot-sample-hypermedia-gson/src/test/java/demo/SpringBootHypermediaApplicationTests.java +++ /dev/null @@ -1,61 +0,0 @@ -package demo; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.http.MediaType; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.web.context.WebApplicationContext; - -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = SpringBootHypermediaApplication.class) -@WebAppConfiguration -@TestPropertySource(properties="endpoints.health.sensitive: false") -public class SpringBootHypermediaApplicationTests { - - @Autowired - private WebApplicationContext context; - - private MockMvc mockMvc; - - @Before - public void setUp() { - this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); - } - - @Test - public void health() throws Exception { - this.mockMvc - .perform(get("/health").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.links[0].href").value("http://localhost/health")) - .andExpect(jsonPath("$.content.status").exists()); - } - - @Test - public void trace() throws Exception { - this.mockMvc - .perform(get("/trace").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.links[0].href").value("http://localhost/trace")) - .andExpect(jsonPath("$.content").isArray()); - } - - @Test - public void envValue() throws Exception { - this.mockMvc.perform(get("/env/user.home").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$._links").doesNotExist()); - } - -} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-gson/src/test/java/sample/hypermedia/gson/SampleHypermediaGsonApplicationTests.java b/spring-boot-samples/spring-boot-sample-hypermedia-gson/src/test/java/sample/hypermedia/gson/SampleHypermediaGsonApplicationTests.java new file mode 100644 index 0000000000..82026259a2 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hypermedia-gson/src/test/java/sample/hypermedia/gson/SampleHypermediaGsonApplicationTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.hypermedia.gson; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.http.MediaType; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import sample.hypermedia.gson.SampleHypermediaGsonApplication; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SampleHypermediaGsonApplication.class) +@WebAppConfiguration +@TestPropertySource(properties = "endpoints.health.sensitive: false") +public class SampleHypermediaGsonApplicationTests { + + @Autowired + private WebApplicationContext context; + + private MockMvc mockMvc; + + @Before + public void setUp() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); + } + + @Test + public void health() throws Exception { + this.mockMvc.perform(get("/health").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.links[0].href").value("http://localhost/health")) + .andExpect(jsonPath("$.content.status").exists()); + } + + @Test + public void trace() throws Exception { + this.mockMvc.perform(get("/trace").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.links[0].href").value("http://localhost/trace")) + .andExpect(jsonPath("$.content").isArray()); + } + + @Test + public void envValue() throws Exception { + this.mockMvc.perform(get("/env/user.home").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$._links").doesNotExist()); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/pom.xml b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/pom.xml index b8ead35e0c..ef99372e65 100644 --- a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/pom.xml +++ b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/pom.xml @@ -2,24 +2,19 @@ 4.0.0 - - spring-boot-sample-hypermedia-jpa - jar - - spring-boot-sample-hypermedia-jpa - Demo project for Spring Boot - + org.springframework.boot spring-boot-samples 1.3.0.BUILD-SNAPSHOT - + spring-boot-sample-hypermedia-jpa + Spring Boot Hypermedia JPA Sample + Spring Boot Hypermedia JPA Sample - UTF-8 + ${basedir}/../.. 1.7 - org.springframework.boot @@ -53,11 +48,6 @@ com.h2database h2 - - org.springframework.boot - spring-boot-devtools - true - org.springframework.boot spring-boot-starter-test @@ -69,7 +59,6 @@ test - @@ -78,5 +67,4 @@ - diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/demo/JpaHypermediaApplication.java b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/demo/JpaHypermediaApplication.java deleted file mode 100644 index baae2f2a8c..0000000000 --- a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/demo/JpaHypermediaApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package demo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class JpaHypermediaApplication { - - public static void main(String[] args) { - SpringApplication.run(JpaHypermediaApplication.class, args); - } - -} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/demo/Book.java b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/sample/hypermedia/jpa/Book.java similarity index 90% rename from spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/demo/Book.java rename to spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/sample/hypermedia/jpa/Book.java index 838c1901bd..7cfb4e0ed5 100644 --- a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/demo/Book.java +++ b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/sample/hypermedia/jpa/Book.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package demo; +package sample.hypermedia.jpa; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -22,14 +22,19 @@ import javax.persistence.Id; @Entity public class Book { + @Id @GeneratedValue private Long id; + private String title; + public String getTitle() { return this.title; } + public void setTitle(String title) { this.title = title; } -} \ No newline at end of file + +} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/demo/BookRepository.java b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/sample/hypermedia/jpa/BookRepository.java similarity index 88% rename from spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/demo/BookRepository.java rename to spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/sample/hypermedia/jpa/BookRepository.java index 6ac159bc81..3a45a77a65 100644 --- a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/demo/BookRepository.java +++ b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/sample/hypermedia/jpa/BookRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,10 @@ * limitations under the License. */ -package demo; +package sample.hypermedia.jpa; import org.springframework.data.jpa.repository.JpaRepository; public interface BookRepository extends JpaRepository { -} \ No newline at end of file + +} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/sample/hypermedia/jpa/SampleHypermediaJpaApplication.java b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/sample/hypermedia/jpa/SampleHypermediaJpaApplication.java new file mode 100644 index 0000000000..ba634f6002 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/main/java/sample/hypermedia/jpa/SampleHypermediaJpaApplication.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.hypermedia.jpa; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SampleHypermediaJpaApplication { + + public static void main(String[] args) { + SpringApplication.run(SampleHypermediaJpaApplication.class, args); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/demo/JpaHypermediaApplicationTests.java b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/demo/JpaHypermediaApplicationTests.java deleted file mode 100644 index 46ac33e2d9..0000000000 --- a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/demo/JpaHypermediaApplicationTests.java +++ /dev/null @@ -1,18 +0,0 @@ -package demo; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = JpaHypermediaApplication.class) -@WebAppConfiguration -public class JpaHypermediaApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/sample/hypermedia/jpa/SampleHypermediaJpaApplicationTests.java b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/sample/hypermedia/jpa/SampleHypermediaJpaApplicationTests.java new file mode 100644 index 0000000000..1014420d0f --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/sample/hypermedia/jpa/SampleHypermediaJpaApplicationTests.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.hypermedia.jpa; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import sample.hypermedia.jpa.SampleHypermediaJpaApplication; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SampleHypermediaJpaApplication.class) +@WebAppConfiguration +public class SampleHypermediaJpaApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/demo/VanillaHypermediaIntegrationTests.java b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/sample/hypermedia/jpa/SampleHypermediaJpaApplicationVanillaIntegrationTests.java similarity index 65% rename from spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/demo/VanillaHypermediaIntegrationTests.java rename to spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/sample/hypermedia/jpa/SampleHypermediaJpaApplicationVanillaIntegrationTests.java index e20d8be0f0..ecdd047e4d 100644 --- a/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/demo/VanillaHypermediaIntegrationTests.java +++ b/spring-boot-samples/spring-boot-sample-hypermedia-jpa/src/test/java/sample/hypermedia/jpa/SampleHypermediaJpaApplicationVanillaIntegrationTests.java @@ -1,9 +1,20 @@ -package demo; +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertEquals; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +package sample.hypermedia.jpa; import org.junit.Before; import org.junit.Test; @@ -20,11 +31,17 @@ import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import sample.hypermedia.jpa.SampleHypermediaJpaApplication; +import static org.junit.Assert.assertEquals; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = JpaHypermediaApplication.class) +@SpringApplicationConfiguration(classes = SampleHypermediaJpaApplication.class) @WebAppConfiguration @DirtiesContext -public class VanillaHypermediaIntegrationTests { +public class SampleHypermediaJpaApplicationVanillaIntegrationTests { @Autowired private WebApplicationContext context; @@ -59,7 +76,8 @@ public class VanillaHypermediaIntegrationTests { @Test public void docs() throws Exception { - MvcResult response = this.mockMvc.perform(get("/admin/docs/").accept(MediaType.TEXT_HTML)) + MvcResult response = this.mockMvc + .perform(get("/admin/docs/").accept(MediaType.TEXT_HTML)) .andExpect(status().isOk()).andReturn(); System.err.println(response.getResponse().getContentAsString()); } @@ -68,7 +86,8 @@ public class VanillaHypermediaIntegrationTests { public void browser() throws Exception { MvcResult response = this.mockMvc.perform(get("/").accept(MediaType.TEXT_HTML)) .andExpect(status().isFound()).andReturn(); - assertEquals("/browser/index.html#", response.getResponse().getHeaders("location").get(0)); + assertEquals("/browser/index.html#", response.getResponse() + .getHeaders("location").get(0)); } } diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-ui/pom.xml b/spring-boot-samples/spring-boot-sample-hypermedia-ui/pom.xml index 2ed2b746cf..ada9bd0e8c 100644 --- a/spring-boot-samples/spring-boot-sample-hypermedia-ui/pom.xml +++ b/spring-boot-samples/spring-boot-sample-hypermedia-ui/pom.xml @@ -2,24 +2,19 @@ 4.0.0 - - spring-boot-sample-hypermedia-ui - jar - - spring-boot-sample-hypermedia-ui - Demo project for Spring Boot - + org.springframework.boot spring-boot-samples 1.3.0.BUILD-SNAPSHOT - + spring-boot-sample-hypermedia-ui + Spring Boot Hypermedia UI Sample + Spring Boot Hypermedia UI Sample - UTF-8 + ${basedir}/../.. 1.7 - org.springframework.boot @@ -37,18 +32,12 @@ org.springframework.boot spring-boot-actuator-docs - - org.springframework.boot - spring-boot-devtools - true - org.springframework.boot spring-boot-starter-test test - @@ -57,5 +46,4 @@ - diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/main/java/demo/SpringBootHypermediaApplication.java b/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/main/java/demo/SpringBootHypermediaApplication.java deleted file mode 100644 index 954faed6f9..0000000000 --- a/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/main/java/demo/SpringBootHypermediaApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package demo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringBootHypermediaApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringBootHypermediaApplication.class, args); - } -} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/main/java/sample/hypermedia/ui/SampleHypermediaUiApplication.java b/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/main/java/sample/hypermedia/ui/SampleHypermediaUiApplication.java new file mode 100644 index 0000000000..51f8f89251 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/main/java/sample/hypermedia/ui/SampleHypermediaUiApplication.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.hypermedia.ui; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SampleHypermediaUiApplication { + + public static void main(String[] args) { + SpringApplication.run(SampleHypermediaUiApplication.class, args); + } +} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/test/java/demo/SpringBootHypermediaApplicationTests.java b/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/test/java/demo/SpringBootHypermediaApplicationTests.java deleted file mode 100644 index 1cf70aeee2..0000000000 --- a/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/test/java/demo/SpringBootHypermediaApplicationTests.java +++ /dev/null @@ -1,18 +0,0 @@ -package demo; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = SpringBootHypermediaApplication.class) -@WebAppConfiguration -public class SpringBootHypermediaApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/test/java/demo/HomePageHypermediaApplicationTests.java b/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/test/java/sample/hypermedia/ui/SampleHypermediaUiApplicationTests.java similarity index 61% rename from spring-boot-samples/spring-boot-sample-hypermedia-ui/src/test/java/demo/HomePageHypermediaApplicationTests.java rename to spring-boot-samples/spring-boot-sample-hypermedia-ui/src/test/java/sample/hypermedia/ui/SampleHypermediaUiApplicationTests.java index e68f6aafe7..abc69e5a59 100644 --- a/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/test/java/demo/HomePageHypermediaApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-hypermedia-ui/src/test/java/sample/hypermedia/ui/SampleHypermediaUiApplicationTests.java @@ -1,6 +1,20 @@ -package demo; +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import static org.junit.Assert.assertTrue; +package sample.hypermedia.ui; import java.net.URI; import java.util.Arrays; @@ -19,26 +33,29 @@ import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; +import sample.hypermedia.ui.SampleHypermediaUiApplication; +import static org.junit.Assert.assertTrue; + @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = SpringBootHypermediaApplication.class) +@SpringApplicationConfiguration(classes = SampleHypermediaUiApplication.class) @WebAppConfiguration @IntegrationTest({ "management.contextPath=", "server.port=0" }) -public class HomePageHypermediaApplicationTests { +public class SampleHypermediaUiApplicationTests { @Value("${local.server.port}") private int port; @Test public void home() { - String response = new TestRestTemplate().getForObject("http://localhost:" + port, - String.class); + String response = new TestRestTemplate().getForObject("http://localhost:" + + this.port, String.class); assertTrue("Wrong body: " + response, response.contains("Hello World")); } @Test public void links() { - String response = new TestRestTemplate().getForObject("http://localhost:" + port + "/links", - String.class); + String response = new TestRestTemplate().getForObject("http://localhost:" + + this.port + "/links", String.class); assertTrue("Wrong body: " + response, response.contains("\"_links\":")); } @@ -47,8 +64,8 @@ public class HomePageHypermediaApplicationTests { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); ResponseEntity response = new TestRestTemplate().exchange( - new RequestEntity(headers , HttpMethod.GET, new URI("http://localhost:" - + port + "/links")), String.class); + new RequestEntity(headers, HttpMethod.GET, new URI( + "http://localhost:" + this.port + "/links")), String.class); assertTrue("Wrong body: " + response, response.getBody().contains("\"_links\":")); } @@ -57,8 +74,8 @@ public class HomePageHypermediaApplicationTests { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); ResponseEntity response = new TestRestTemplate().exchange( - new RequestEntity(headers , HttpMethod.GET, new URI("http://localhost:" - + port)), String.class); + new RequestEntity(headers, HttpMethod.GET, new URI( + "http://localhost:" + this.port)), String.class); assertTrue("Wrong body: " + response, response.getBody().contains("Hello World")); } diff --git a/spring-boot-samples/spring-boot-sample-hypermedia/pom.xml b/spring-boot-samples/spring-boot-sample-hypermedia/pom.xml index a937dc548c..2c2900038f 100644 --- a/spring-boot-samples/spring-boot-sample-hypermedia/pom.xml +++ b/spring-boot-samples/spring-boot-sample-hypermedia/pom.xml @@ -2,24 +2,20 @@ 4.0.0 - - spring-boot-sample-hypermedia - jar - - spring-boot-sample-hypermedia - Demo project for Spring Boot - + org.springframework.boot spring-boot-samples 1.3.0.BUILD-SNAPSHOT - + spring-boot-sample-hypermedia + Spring Boot Hypermedia Sample + Spring Boot Hypermedia Sample + ${basedir}/../.. UTF-8 1.7 - org.springframework.boot @@ -41,18 +37,12 @@ org.webjars hal-browser - - org.springframework.boot - spring-boot-devtools - true - org.springframework.boot spring-boot-starter-test test - @@ -61,5 +51,4 @@ - diff --git a/spring-boot-samples/spring-boot-sample-hypermedia/src/main/java/demo/SpringBootHypermediaApplication.java b/spring-boot-samples/spring-boot-sample-hypermedia/src/main/java/demo/SpringBootHypermediaApplication.java deleted file mode 100644 index 954faed6f9..0000000000 --- a/spring-boot-samples/spring-boot-sample-hypermedia/src/main/java/demo/SpringBootHypermediaApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package demo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SpringBootHypermediaApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringBootHypermediaApplication.class, args); - } -} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia/src/main/java/sample/hypermedia/SampleHypermediaApplication.java b/spring-boot-samples/spring-boot-sample-hypermedia/src/main/java/sample/hypermedia/SampleHypermediaApplication.java new file mode 100644 index 0000000000..ab624de83a --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-hypermedia/src/main/java/sample/hypermedia/SampleHypermediaApplication.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.hypermedia; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SampleHypermediaApplication { + + public static void main(String[] args) { + SpringApplication.run(SampleHypermediaApplication.class, args); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia/src/test/java/demo/SpringBootHypermediaApplicationTests.java b/spring-boot-samples/spring-boot-sample-hypermedia/src/test/java/demo/SpringBootHypermediaApplicationTests.java deleted file mode 100644 index fc06e71649..0000000000 --- a/spring-boot-samples/spring-boot-sample-hypermedia/src/test/java/demo/SpringBootHypermediaApplicationTests.java +++ /dev/null @@ -1,18 +0,0 @@ -package demo; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; - -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = SpringBootHypermediaApplication.class) -@WebAppConfiguration -public class SpringBootHypermediaApplicationTests { - - @Test - public void contextLoads() { - } - -} diff --git a/spring-boot-samples/spring-boot-sample-hypermedia/src/test/java/demo/HomePageHypermediaApplicationTests.java b/spring-boot-samples/spring-boot-sample-hypermedia/src/test/java/sample/hypermedia/SampleHypermediaApplicationHomePageTests.java similarity index 62% rename from spring-boot-samples/spring-boot-sample-hypermedia/src/test/java/demo/HomePageHypermediaApplicationTests.java rename to spring-boot-samples/spring-boot-sample-hypermedia/src/test/java/sample/hypermedia/SampleHypermediaApplicationHomePageTests.java index 676a937971..aa43e36498 100644 --- a/spring-boot-samples/spring-boot-sample-hypermedia/src/test/java/demo/HomePageHypermediaApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-hypermedia/src/test/java/sample/hypermedia/SampleHypermediaApplicationHomePageTests.java @@ -1,6 +1,20 @@ -package demo; +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import static org.junit.Assert.assertTrue; +package sample.hypermedia; import java.net.URI; import java.util.Arrays; @@ -19,19 +33,21 @@ import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; +import static org.junit.Assert.assertTrue; + @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = SpringBootHypermediaApplication.class) +@SpringApplicationConfiguration(classes = SampleHypermediaApplication.class) @WebAppConfiguration @IntegrationTest("server.port=0") -public class HomePageHypermediaApplicationTests { +public class SampleHypermediaApplicationHomePageTests { @Value("${local.server.port}") private int port; @Test public void home() { - String response = new TestRestTemplate().getForObject("http://localhost:" + port, - String.class); + String response = new TestRestTemplate().getForObject("http://localhost:" + + this.port, String.class); assertTrue("Wrong body: " + response, response.contains("\"_links\":")); assertTrue("Wrong body: " + response, response.contains("\"curies\":")); } @@ -41,8 +57,8 @@ public class HomePageHypermediaApplicationTests { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); ResponseEntity response = new TestRestTemplate().exchange( - new RequestEntity(headers , HttpMethod.GET, new URI("http://localhost:" - + port + "/")), String.class); + new RequestEntity(headers, HttpMethod.GET, new URI( + "http://localhost:" + this.port + "/")), String.class); assertTrue("Wrong body: " + response, response.getBody().contains("\"_links\":")); } @@ -51,8 +67,8 @@ public class HomePageHypermediaApplicationTests { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); ResponseEntity response = new TestRestTemplate().exchange( - new RequestEntity(headers , HttpMethod.GET, new URI("http://localhost:" - + port)), String.class); + new RequestEntity(headers, HttpMethod.GET, new URI( + "http://localhost:" + this.port)), String.class); assertTrue("Wrong body: " + response, response.getBody().contains("HAL Browser")); }