#1080 - Improved configuration setup and documentation on EntityLinks.
We now explicitly only enable EntityLinks in WebMVC environments. This is also now reflected properly in the reference documentation.
This commit is contained in:
@@ -267,6 +267,10 @@ curl -v localhost:8080/employees \
|
||||
[[server.entity-links]]
|
||||
== [[fundamentals.obtaining-links.entity-links]] Using the EntityLinks interface
|
||||
|
||||
IMPORTANT: `EntityLinks` and it's various implementations are NOT currently provided out-of-the-box for Spring WebFlux applications.
|
||||
The contract defined in the `EntityLinks` SPI was originally aimed at Spring Web MVC and doesn't consider Reactor types.
|
||||
Developing a comparable contract that supports reactive programming is still in progress.
|
||||
|
||||
So far, we have created links by pointing to the web-framework implementations (that is, the Spring MVC controllers) and inspected the mapping.
|
||||
In many cases, these classes essentially read and write representations backed by a model class.
|
||||
|
||||
@@ -285,13 +289,13 @@ Link link = links.linkToItemResource(Customer.class, 1L);
|
||||
|
||||
`EntityLinks` is available via dependency injection by activating `@EnableHypermediaSupprt` in your Spring MVC configuration.
|
||||
This will cause a variety of default implementations of `EntityLinks` being registered.
|
||||
The most fundamental one is `ControllerEntityLinks` that inspects SpringMVC and Spring WebFlux controller classes.
|
||||
The most fundamental one is `ControllerEntityLinks` that inspects SpringMVC controller classes.
|
||||
If you want to register your own implementation of `EntityLinks`, check out <<server.entity-links.spi, this section>>.
|
||||
|
||||
[[server.entity-links.controller]]
|
||||
=== EntityLinks based on Spring MVC and WebFlux controllers
|
||||
=== EntityLinks based on Spring MVC controllers
|
||||
|
||||
Activating entity links functionality causes all the Spring MVC and WebFlux controllers available in the current `ApplicationContext` to be inspected for the `@ExposesResourceFor(…)` annotation.
|
||||
Activating entity links functionality causes all the Spring MVC controllers available in the current `ApplicationContext` to be inspected for the `@ExposesResourceFor(…)` annotation.
|
||||
The annotation exposes which model type the controller manages.
|
||||
Beyond that, we assume that you adhere to following the URI mapping setup and conventions:
|
||||
|
||||
@@ -421,10 +425,6 @@ It's registered as primary bean so that it's always the sole injection candidate
|
||||
`ControllerEntityLinks` is the default implementation that will be included in the setup, but users are free to implement and register their own implementations.
|
||||
Making those available to the `EntityLinks` instance available for injection is a matter of registering your implementation as Spring bean.
|
||||
|
||||
IMPORTANT: `EntityLinks` and it's various implementations are NOT currently provided out-of-the-box for Spring WebFlux applications.
|
||||
The contract defined in the `EntityLinks` SPI was originally aimed at Spring Web MVC and doesn't consider Reactor types.
|
||||
Developing a comparable contract that supports reactive programming is still in progress.
|
||||
|
||||
.Declaring a custom EntityLinks implementation
|
||||
====
|
||||
[source, java]
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.context.support.AbstractMessageSource;
|
||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
||||
@@ -58,7 +57,6 @@ import org.springframework.util.ClassUtils;
|
||||
* @since 0.19
|
||||
*/
|
||||
@Configuration
|
||||
@Import(EntityLinksConfiguration.class)
|
||||
@EnablePluginRegistries({ LinkDiscoverer.class })
|
||||
public class HateoasConfiguration {
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.stereotype.Controller;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
class WebMvcEntityLinksConfiguration {
|
||||
class WebMvcEntityLinksConfiguration extends EntityLinksConfiguration {
|
||||
|
||||
@Bean
|
||||
ControllerEntityLinksFactoryBean webMvcEntityLinks(ObjectProvider<WebMvcLinkBuilderFactory> linkBuilderFactory) {
|
||||
|
||||
@@ -18,9 +18,12 @@ package org.springframework.hateoas.config;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.StandardAnnotationMetadata;
|
||||
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
|
||||
import org.springframework.hateoas.server.EntityLinks;
|
||||
import org.springframework.hateoas.support.WebStack;
|
||||
|
||||
/**
|
||||
@@ -35,7 +38,7 @@ class WebStackImportSelectorUnitTest {
|
||||
@Test // #973
|
||||
void activatesAllWebStacksByDefault() {
|
||||
|
||||
AnnotationMetadata metadata = new StandardAnnotationMetadata(DefaultHypermedia.class);
|
||||
AnnotationMetadata metadata = AnnotationMetadata.introspect(DefaultHypermedia.class);
|
||||
|
||||
assertThat(selector.selectImports(metadata))
|
||||
.containsExactlyInAnyOrderElementsOf(WebStackImportSelector.CONFIGS.values());
|
||||
@@ -44,7 +47,7 @@ class WebStackImportSelectorUnitTest {
|
||||
@Test // #973
|
||||
void activatesWebMvcOnlyifConfigured() {
|
||||
|
||||
AnnotationMetadata metadata = new StandardAnnotationMetadata(WebMvcHypermedia.class);
|
||||
AnnotationMetadata metadata = AnnotationMetadata.introspect(WebMvcHypermedia.class);
|
||||
|
||||
assertThat(selector.selectImports(metadata)).containsExactly(WebStackImportSelector.CONFIGS.get(WebStack.WEBMVC));
|
||||
}
|
||||
@@ -52,7 +55,7 @@ class WebStackImportSelectorUnitTest {
|
||||
@Test // #973
|
||||
void activatesWebFluxOnlyIfConfigured() {
|
||||
|
||||
AnnotationMetadata metadata = new StandardAnnotationMetadata(WebFluxHypermedia.class);
|
||||
AnnotationMetadata metadata = AnnotationMetadata.introspect(WebFluxHypermedia.class);
|
||||
|
||||
assertThat(selector.selectImports(metadata)).containsExactly(WebStackImportSelector.CONFIGS.get(WebStack.WEBFLUX));
|
||||
}
|
||||
@@ -60,13 +63,23 @@ class WebStackImportSelectorUnitTest {
|
||||
@Test // #973
|
||||
void rejectsNoStacksSelected() {
|
||||
|
||||
AnnotationMetadata metadata = new StandardAnnotationMetadata(NoStacksHypermedia.class);
|
||||
AnnotationMetadata metadata = AnnotationMetadata.introspect(NoStacksHypermedia.class);
|
||||
|
||||
assertThatExceptionOfType(IllegalStateException.class) //
|
||||
.isThrownBy(() -> selector.selectImports(metadata)) //
|
||||
.withMessageContaining(NoStacksHypermedia.class.getName());
|
||||
}
|
||||
|
||||
@Test // #1080
|
||||
void noEntityLinksRegisteredForWebFluxBootstrap() throws Exception {
|
||||
|
||||
try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(WebFluxHypermedia.class)) {
|
||||
|
||||
assertThatExceptionOfType(NoSuchBeanDefinitionException.class) //
|
||||
.isThrownBy(() -> context.getBean(EntityLinks.class));
|
||||
}
|
||||
}
|
||||
|
||||
@EnableHypermediaSupport(type = HypermediaType.HAL)
|
||||
static class DefaultHypermedia {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user