Workaround problems with order of endpoint handler mapping
When Spring Data REST is owning the home page it has its own HandlerMapping with a fix (relatively) low priority. The /links endpoint wants to own the home page as well, and our handler mapping has a high priority for good reasons. This change addresses the issue by checking if Spring Data REST is configured and if the management context path (or more specifically, the links endpoint) is the same as the home page. Fixes gh-3486
This commit is contained in:
parent
e22ae39b35
commit
de95012635
|
|
@ -45,22 +45,22 @@
|
|||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-xml</artifactId>
|
||||
<optional>true</optional>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.hateoas</groupId>
|
||||
<artifactId>spring-hateoas</artifactId>
|
||||
<optional>true</optional>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.plugin</groupId>
|
||||
<artifactId>spring-plugin-core</artifactId>
|
||||
<optional>true</optional>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>hal-browser</artifactId>
|
||||
<optional>true</optional>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
|
|
@ -161,6 +161,13 @@
|
|||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-solr</artifactId>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<!-- the version of solr here is incompatible with jackson-xml because of an old woodstox -->
|
||||
<exclusion>
|
||||
<artifactId>wstx-asl</artifactId>
|
||||
<groupId>org.codehaus.woodstox</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
|
||||
|
|
@ -90,11 +91,11 @@ 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, RepositoryRestMvcAutoConfiguration.class,
|
||||
HypermediaAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class })
|
||||
public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
||||
BeanFactoryAware, SmartInitializingSingleton {
|
||||
BeanFactoryAware, SmartInitializingSingleton {
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(EndpointWebMvcAutoConfiguration.class);
|
||||
|
|
@ -129,7 +130,7 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
|||
if (managementPort == ManagementServerPort.DIFFERENT
|
||||
&& this.applicationContext instanceof EmbeddedWebApplicationContext
|
||||
&& ((EmbeddedWebApplicationContext) this.applicationContext)
|
||||
.getEmbeddedServletContainer() != null) {
|
||||
.getEmbeddedServletContainer() != null) {
|
||||
createChildManagementContext();
|
||||
}
|
||||
if (managementPort == ManagementServerPort.SAME
|
||||
|
|
@ -149,7 +150,7 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
|||
EmbeddedServletContainerAutoConfiguration.class,
|
||||
DispatcherServletAutoConfiguration.class);
|
||||
CloseEventPropagationListener
|
||||
.addIfPossible(this.applicationContext, childContext);
|
||||
.addIfPossible(this.applicationContext, childContext);
|
||||
try {
|
||||
childContext.refresh();
|
||||
managementContextResolver().setApplicationContext(childContext);
|
||||
|
|
@ -221,7 +222,7 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
|||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
throws ServletException, IOException {
|
||||
if (this.properties == null) {
|
||||
this.properties = this.applicationContext
|
||||
.getBean(ManagementServerProperties.class);
|
||||
|
|
@ -240,7 +241,7 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
|||
* parent to a child.
|
||||
*/
|
||||
private static class CloseEventPropagationListener implements
|
||||
ApplicationListener<ContextClosedEvent> {
|
||||
ApplicationListener<ContextClosedEvent> {
|
||||
|
||||
private final ApplicationContext parentContext;
|
||||
|
||||
|
|
@ -275,7 +276,7 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
|||
}
|
||||
|
||||
private static class OnManagementMvcCondition extends SpringBootCondition implements
|
||||
ConfigurationCondition {
|
||||
ConfigurationCondition {
|
||||
|
||||
@Override
|
||||
public ConfigurationPhase getConfigurationPhase() {
|
||||
|
|
@ -324,7 +325,7 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
|||
return ((managementPort == null)
|
||||
|| (serverPort == null && managementPort.equals(8080))
|
||||
|| (managementPort != 0 && managementPort.equals(serverPort)) ? SAME
|
||||
: DIFFERENT);
|
||||
: DIFFERENT);
|
||||
}
|
||||
|
||||
private static Integer getPortProperty(Environment environment, String prefix) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
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;
|
||||
|
|
@ -23,7 +25,11 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.ActuatorDocsEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HalBrowserEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HypermediaDisabled;
|
||||
|
|
@ -41,6 +47,7 @@ import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
|||
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
|
||||
import org.springframework.boot.autoconfigure.web.ResourceProperties;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
|
|
@ -48,7 +55,9 @@ import org.springframework.context.annotation.Conditional;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.core.type.MethodMetadata;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
|
|
@ -61,6 +70,7 @@ import org.springframework.http.converter.HttpMessageNotWritableException;
|
|||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.TypeUtils;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
|
|
@ -74,8 +84,6 @@ 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;
|
||||
|
||||
/**
|
||||
* Configuration for hypermedia in HTTP endpoints.
|
||||
*
|
||||
|
|
@ -128,7 +136,7 @@ public class EndpointWebMvcHypermediaManagementContextConfiguration {
|
|||
@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,
|
||||
|
|
@ -149,12 +157,106 @@ public class EndpointWebMvcHypermediaManagementContextConfiguration {
|
|||
@ConditionalOnProperty(value = "endpoints.links.enabled", matchIfMissing = true)
|
||||
public static class LinksConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ListableBeanFactory beanFactory;
|
||||
|
||||
@Autowired
|
||||
private ManagementServerProperties management;
|
||||
|
||||
@Bean
|
||||
@Conditional(NotSpringDataRestHomePageCondition.class)
|
||||
public LinksMvcEndpoint linksMvcEndpoint(ResourceProperties resources) {
|
||||
String defaultPath = (resources.getWelcomePage() != null ? "/links" : "");
|
||||
String defaultPath = getDefaultPath(resources);
|
||||
return new LinksMvcEndpoint(defaultPath);
|
||||
}
|
||||
|
||||
private String getDefaultPath(ResourceProperties resources) {
|
||||
return resources.getWelcomePage() != null ? "/links" : "";
|
||||
}
|
||||
|
||||
private static class NotSpringDataRestHomePageCondition extends
|
||||
SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
if (!ClassUtils
|
||||
.isPresent(
|
||||
"org.springframework.data.rest.core.config.RepositoryRestConfiguration",
|
||||
null)) {
|
||||
return ConditionOutcome.match("Spring Data REST is not present");
|
||||
}
|
||||
Class<?> type = ClassUtils
|
||||
.resolveClassName(
|
||||
"org.springframework.data.rest.core.config.RepositoryRestConfiguration",
|
||||
null);
|
||||
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
|
||||
if (beanFactory.getBeanNamesForType(type, true, false).length == 0) {
|
||||
return ConditionOutcome.match("Spring Data REST is not configured");
|
||||
}
|
||||
Environment environment = context.getEnvironment();
|
||||
String path = getProperty(environment, "management.", "contextPath");
|
||||
if (path == null
|
||||
&& hasCustomBeanDefinition(beanFactory,
|
||||
ManagementServerProperties.class,
|
||||
ManagementServerPropertiesAutoConfiguration.class)) {
|
||||
ManagementServerProperties bean = beanFactory
|
||||
.getBean(ManagementServerProperties.class);
|
||||
path = bean.getContextPath();
|
||||
}
|
||||
if (isHome(path)) {
|
||||
path = getProperty(environment, "endpoints.links.", "path");
|
||||
if (isHome(path)) {
|
||||
return ConditionOutcome
|
||||
.noMatch("Management context path is home and so is links path");
|
||||
}
|
||||
else {
|
||||
return ConditionOutcome
|
||||
.match("Management context path is home but links path is not: '"
|
||||
+ path + "'");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// N.B. we don't cover the case where the user has Spring Data REST
|
||||
// but changes *its* home page - you'd have to instantiate the
|
||||
// RepositoryRestConfiguration and look at it's basePath for that.
|
||||
return ConditionOutcome
|
||||
.match("Management context path is not home: '" + path + "'");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isHome(String path) {
|
||||
return path == null || "".equals(path) || "/".equals(path);
|
||||
}
|
||||
|
||||
private static String getProperty(Environment environment, String prefix,
|
||||
String name) {
|
||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
|
||||
environment, prefix);
|
||||
return resolver.getProperty(name, String.class);
|
||||
}
|
||||
|
||||
private static <T> boolean hasCustomBeanDefinition(
|
||||
ConfigurableListableBeanFactory beanFactory, Class<T> type,
|
||||
Class<?> configClass) {
|
||||
String[] names = beanFactory.getBeanNamesForType(type, true, false);
|
||||
if (names == null || names.length != 1) {
|
||||
return false;
|
||||
}
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition(names[0]);
|
||||
if (definition instanceof AnnotatedBeanDefinition) {
|
||||
MethodMetadata factoryMethodMetadata = ((AnnotatedBeanDefinition) definition)
|
||||
.getFactoryMethodMetadata();
|
||||
if (factoryMethodMetadata != null) {
|
||||
String className = factoryMethodMetadata.getDeclaringClassName();
|
||||
return !configClass.getName().equals(className);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
@ -166,7 +268,7 @@ public class EndpointWebMvcHypermediaManagementContextConfiguration {
|
|||
@Autowired
|
||||
private MvcEndpoints endpoints;
|
||||
|
||||
@Autowired
|
||||
@Autowired(required = false)
|
||||
private LinksMvcEndpoint linksEndpoint;
|
||||
|
||||
@Autowired
|
||||
|
|
@ -200,7 +302,7 @@ public class EndpointWebMvcHypermediaManagementContextConfiguration {
|
|||
public Object beforeBodyWrite(Object body, MethodParameter returnType,
|
||||
MediaType selectedContentType,
|
||||
Class<? extends HttpMessageConverter<?>> selectedConverterType,
|
||||
ServerHttpRequest request, ServerHttpResponse response) {
|
||||
ServerHttpRequest request, ServerHttpResponse response) {
|
||||
if (request instanceof ServletServerHttpRequest) {
|
||||
beforeBodyWrite(body, (ServletServerHttpRequest) request);
|
||||
}
|
||||
|
|
@ -217,8 +319,8 @@ public class EndpointWebMvcHypermediaManagementContextConfiguration {
|
|||
if (isHomePage(path) && hasManagementPath()) {
|
||||
String rel = this.management.getContextPath().substring(1);
|
||||
resource.add(linkTo(
|
||||
EndpointWebMvcHypermediaManagementContextConfiguration.class).slash(
|
||||
this.management.getContextPath()).withRel(rel));
|
||||
EndpointWebMvcHypermediaManagementContextConfiguration.class)
|
||||
.slash(this.management.getContextPath()).withRel(rel));
|
||||
}
|
||||
else {
|
||||
this.linksEnhancer.addEndpointLinks(resource, "");
|
||||
|
|
@ -236,8 +338,9 @@ public class EndpointWebMvcHypermediaManagementContextConfiguration {
|
|||
}
|
||||
|
||||
private boolean isLinksPath(String path) {
|
||||
return (this.management.getContextPath() + this.linksEndpoint.getPath())
|
||||
.equals(path);
|
||||
return this.linksEndpoint != null
|
||||
&& (this.management.getContextPath() + this.linksEndpoint
|
||||
.getPath()).equals(path);
|
||||
}
|
||||
|
||||
private boolean isHomePage(String path) {
|
||||
|
|
@ -280,7 +383,7 @@ public class EndpointWebMvcHypermediaManagementContextConfiguration {
|
|||
public Object beforeBodyWrite(Object body, MethodParameter returnType,
|
||||
MediaType selectedContentType,
|
||||
Class<? extends HttpMessageConverter<?>> selectedConverterType,
|
||||
ServerHttpRequest request, ServerHttpResponse response) {
|
||||
ServerHttpRequest request, ServerHttpResponse response) {
|
||||
if (request instanceof ServletServerHttpRequest) {
|
||||
return beforeBodyWrite(body, returnType, selectedContentType,
|
||||
selectedConverterType, (ServletServerHttpRequest) request,
|
||||
|
|
@ -292,7 +395,7 @@ public class EndpointWebMvcHypermediaManagementContextConfiguration {
|
|||
private Object beforeBodyWrite(Object body, MethodParameter returnType,
|
||||
MediaType selectedContentType,
|
||||
Class<? extends HttpMessageConverter<?>> selectedConverterType,
|
||||
ServletServerHttpRequest request, ServerHttpResponse response) {
|
||||
ServletServerHttpRequest request, ServerHttpResponse response) {
|
||||
if (body == null || body instanceof Resource) {
|
||||
// Assume it already was handled or it already has its links
|
||||
return body;
|
||||
|
|
@ -317,7 +420,7 @@ public class EndpointWebMvcHypermediaManagementContextConfiguration {
|
|||
@SuppressWarnings("unchecked")
|
||||
private HttpMessageConverter<Object> findConverter(
|
||||
Class<? extends HttpMessageConverter<?>> selectedConverterType,
|
||||
MediaType mediaType) {
|
||||
MediaType mediaType) {
|
||||
if (this.converterCache.containsKey(mediaType)) {
|
||||
return (HttpMessageConverter<Object>) this.converterCache
|
||||
.get(mediaType);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
|
|||
* @author Dave Syer
|
||||
*/
|
||||
public class EndpointHandlerMapping extends RequestMappingHandlerMapping implements
|
||||
ApplicationContextAware {
|
||||
ApplicationContextAware {
|
||||
|
||||
private final Set<MvcEndpoint> endpoints;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,12 +16,16 @@
|
|||
|
||||
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;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
|
@ -38,11 +42,12 @@ import org.springframework.boot.actuate.endpoint.Endpoint;
|
|||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMappingCustomizer;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
|
||||
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
|
|
@ -51,6 +56,7 @@ import org.springframework.boot.test.TestRestTemplate;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
|
@ -60,9 +66,6 @@ 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.
|
||||
*
|
||||
|
|
@ -82,7 +85,7 @@ public class EndpointMvcIntegrationTests {
|
|||
private TestInterceptor interceptor;
|
||||
|
||||
@Test
|
||||
public void envEndpointNotHidden() throws InterruptedException {
|
||||
public void envEndpointHidden() throws InterruptedException {
|
||||
String body = new TestRestTemplate().getForObject("http://localhost:" + this.port
|
||||
+ "/env/user.dir", String.class);
|
||||
assertNotNull(body);
|
||||
|
|
@ -90,14 +93,23 @@ public class EndpointMvcIntegrationTests {
|
|||
assertTrue(this.interceptor.invoked());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthEndpointNotHidden() throws InterruptedException {
|
||||
String body = new TestRestTemplate().getForObject("http://localhost:" + this.port
|
||||
+ "/health", String.class);
|
||||
assertNotNull(body);
|
||||
assertTrue("Wrong body: \n" + body, body.contains("status"));
|
||||
assertTrue(this.interceptor.invoked());
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@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, ErrorMvcAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class })
|
||||
protected static @interface MinimalWebConfiguration {
|
||||
|
||||
}
|
||||
|
|
@ -105,8 +117,8 @@ public class EndpointMvcIntegrationTests {
|
|||
@Configuration
|
||||
@MinimalWebConfiguration
|
||||
@Import({ ManagementServerPropertiesAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
EndpointWebMvcAutoConfiguration.class })
|
||||
JacksonAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
EndpointWebMvcAutoConfiguration.class })
|
||||
@RestController
|
||||
protected static class Application {
|
||||
|
||||
|
|
@ -122,6 +134,15 @@ public class EndpointMvcIntegrationTests {
|
|||
return Collections.singletonMap("foo", (Object) "bar");
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
private final List<HttpMessageConverter<?>> converters = Collections.emptyList();
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public HttpMessageConverters messageConverters() {
|
||||
return new HttpMessageConverters(this.converters);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EndpointHandlerMappingCustomizer mappingCustomizer() {
|
||||
return new EndpointHandlerMappingCustomizer() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 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.actuate.endpoint.mvc.MvcEndpoints;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
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.MvcResult;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@WebAppConfiguration
|
||||
@SpringApplicationConfiguration(classes = SampleHypermediaJpaApplication.class)
|
||||
@DirtiesContext
|
||||
@TestPropertySource(properties = { "debug=true", "management.contextPath=",
|
||||
"endpoints.docs.curies.enabled=false" })
|
||||
public class SampleHypermediaJpaApplicationCustomLinksPathIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private MvcEndpoints mvcEndpoints;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void links() throws Exception {
|
||||
this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links").exists())
|
||||
.andExpect(jsonPath("$._links.health").exists())
|
||||
.andExpect(jsonPath("$._links.books").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void health() throws Exception {
|
||||
this.mockMvc.perform(get("/health").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void docs() throws Exception {
|
||||
MvcResult response = this.mockMvc
|
||||
.perform(get("/docs/").accept(MediaType.TEXT_HTML))
|
||||
.andExpect(status().isOk()).andReturn();
|
||||
System.err.println(response.getResponse().getContentAsString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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 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.actuate.endpoint.mvc.MvcEndpoints;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
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.MvcResult;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@WebAppConfiguration
|
||||
@SpringApplicationConfiguration(classes = SampleHypermediaJpaApplication.class)
|
||||
@DirtiesContext
|
||||
@TestPropertySource(properties = { "endpoints.links.path=/admin", "management.contextPath=",
|
||||
"endpoints.docs.curies.enabled=false" })
|
||||
public class SampleHypermediaJpaApplicationSharedRootIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private MvcEndpoints mvcEndpoints;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void home() throws Exception {
|
||||
this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links").exists())
|
||||
.andExpect(jsonPath("$._links.health").exists())
|
||||
.andExpect(jsonPath("$._links.admin").exists())
|
||||
.andExpect(jsonPath("$._links.books").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void health() throws Exception {
|
||||
this.mockMvc.perform(get("/health").accept(MediaType.APPLICATION_JSON))
|
||||
.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.health").exists())
|
||||
.andExpect(jsonPath("$._links").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void docs() throws Exception {
|
||||
MvcResult response = this.mockMvc
|
||||
.perform(get("/docs/").accept(MediaType.TEXT_HTML))
|
||||
.andExpect(status().isOk()).andReturn();
|
||||
System.err.println(response.getResponse().getContentAsString());
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue