diff --git a/src/docbkx/repositories.xml b/src/docbkx/repositories.xml
index b91a467fb..7cacd1650 100644
--- a/src/docbkx/repositories.xml
+++ b/src/docbkx/repositories.xml
@@ -855,73 +855,91 @@ public class MyRepositoryFactoryBean<R extends JpaRepository<T, I>, T,
Spring Data usage in a variety of contexts. Currently most of the
integration is targeted towards Spring MVC.
-
- Domain class web binding for Spring MVC
+
+ Web support
- Given you are developing a Spring MVC web application you
- typically have to resolve domain class ids from URLs. By default your
- task is to transform that request parameter or URL part into the domain
- class to hand it to layers below then or execute business logic on the
- entities directly. This would look something like this:
+
+ This section contains the documentation for the Spring Data web
+ support as it is implemented as of Spring Data Commons in the 1.6
+ range. As it the newly introduced support changes quite a lot of
+ things we kept the documentation of the former behavior in .
+
- @Controller
-@RequestMapping("/users")
-public class UserController {
+ Spring Data modules ships with a variety of web support if the
+ module supports the repository programming model. The web related stuff
+ requires Spring MVC JARs on the classpath, some of them even provide
+ integration with Spring HATEOAS.
- private final UserRepository userRepository;
+
+ Spring HATEOAS - https://github.com/SpringSource/spring-hateoas
+ In general, the integration support is enabled by using the
+ @EnableSpringDataWebSupport annotation in
+ your JavaConfig configuration class.
- @Autowired
- public UserController(UserRepository userRepository) {
- Assert.notNull(repository, "Repository must not be null!");
- userRepository = userRepository;
- }
+
+ Enabling Spring Data web support
- @RequestMapping("/{id}")
- public String showUserForm(@PathVariable("id") Long id, Model model) {
-
- // Do null check for id
- User user = userRepository.findOne(id);
- // Do null check for user
+ @Configuration
+@EnableWebMvc
+@EnableSpringDataWebSupport
+class WebConfiguration { }
+
- model.addAttribute("user", user);
- return "user";
- }
-}
+ The @EnableSpringDataWebSupport annotation registers a few
+ components we will discuss in a bit. It will also detect Spring HATEOAS
+ on the classpath and register integration components for it as well if
+ present.
- First you declare a repository dependency for each controller to
- look up the entity managed by the controller or repository respectively.
- Looking up the entity is boilerplate as well, as it's always a
- findOne(…) call. Fortunately Spring provides
- means to register custom components that allow conversion between a
- String value to an arbitrary type.
+ Alternatively, if you are using XML configuration, register either
+ SpringDataWebSupport or HateoasAwareSpringDataWebSupport as Spring
+ beans:
-
- PropertyEditors
+
+ Enabling Spring Data web support in XML
- For Spring versions before 3.0 simple Java
- PropertyEditors had to be used. To
- integrate with that, Spring Data offers a
- DomainClassPropertyEditorRegistrar, which looks
- up all Spring Data repositories registered in the
- ApplicationContext and registers a
- custom PropertyEditor for the managed
- domain class.
+ <bean class="org.springframework.data.web.config.SpringDataWebConfiguration" />
- <bean class="….web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
- <property name="webBindingInitializer">
- <bean class="….web.bind.support.ConfigurableWebBindingInitializer">
- <property name="propertyEditorRegistrars">
- <bean class="org.springframework.data.repository.support.DomainClassPropertyEditorRegistrar" />
- </property>
- </bean>
- </property>
-</bean>
+<!-- If you're using Spring HATEOAS as well register this one *instead* of the former -->
+<bean class="org.springframework.data.web.config.HateoasAwareSpringDataWebConfiguration" />
+
- If you have configured Spring MVC as in the preceding example,
- you can configure your controller as follows, which reduces a lot of
- the clutter and boilerplate.
+
+ Basic web support
- @Controller
+ The configuration setup shown above will register a few basic
+ components:
+
+
+
+ A DomainClassConverter to enable
+ Spring MVC to resolve instances of repository managed domain
+ classes from request parameters or path variables.
+
+
+
+ HandlerMethodArgumentResolver
+ implementations to let Spring MVC resolve
+ Pageable and
+ Sort instances from request
+ parameters.
+
+
+
+
+ DomainClassConverter
+
+ The DomainClassConverter allows you to
+ use domain types in your Spring MVC controller method signatures
+ directly, so that you don't have to manually lookup the instances
+ via the repository:
+
+
+ A Spring MVC controller using domain types in method
+ signatures
+
+ @Controller
@RequestMapping("/users")
public class UserController {
@@ -932,203 +950,208 @@ public class UserController {
return "userForm";
}
}
-
+
-
- ConversionService
+ As you can see the method receives a User instance directly
+ and no further lookup is necessary. The instance can be resolved by
+ letting Spring MVC convert the path variable into the id type of the
+ domain class first and eventually access the instance through
+ calling findOne(…) on the repository
+ instance registered for the domain type.
- In Spring 3.0 and later the
- PropertyEditor support is superseded by
- a new conversion infrastructure that eliminates the drawbacks of
- PropertyEditors and uses a stateless X
- to Y conversion approach. Spring Data now ships with a
- DomainClassConverter that mimics the behavior
- of DomainClassPropertyEditorRegistrar. To
- configure, simply declare a bean instance and pipe the
- ConversionService being used into its
- constructor:
+
+ Currently the repository has to implement
+ CrudRepository to be eligible to be
+ discovered for conversion.
+
+
- <mvc:annotation-driven conversion-service="conversionService" />
+
+ HandlerMethodArgumentResolvers for Pageable and Sort
-<bean class="org.springframework.data.repository.support.DomainClassConverter">
- <constructor-arg ref="conversionService" />
-</bean>
+ The configuration snippet above also registers a
+ PageableHandlerMethodArgumentResolver as well
+ as an instance of
+ SortHandlerMethodArgumentResolver. The
+ registration enables Pageable and
+ Sort being valid controller method
+ arguments
- If you are using JavaConfig, you can simply extend Spring MVC's
- WebMvcConfigurationSupport and hand the
- FormatingConversionService that the
- configuration superclass provides into the
- DomainClassConverter instance you
- create.
+
+ Using Pageable as controller method argument
- class WebConfiguration extends WebMvcConfigurationSupport {
-
- // Other configuration omitted
-
- @Bean
- public DomainClassConverter<?> domainClassConverter() {
- return new DomainClassConverter<FormattingConversionService>(mvcConversionService());
- }
-}
-
-
-
-
- The PageableArgumentResolver will use a
- PageRequest with the first page and a page size
- of 10 by default. It will use that value if it cannot resolve a
- PageRequest from the request (because of
- missing parameters, for example). You can configure a global default
- on the bean declaration directly. If you might need controller method
- specific defaults for the Pageable,
- annotate the method parameter with
- @PageableDefaults and specify page
- (through pageNumber), page size (through
- value), sort (list of properties to sort
- by), and sortDir (the direction to sort by) as annotation
- attributes:
+ Spring HATEOAS ships with a representation model class
+ PagedResources that allows enrichting the content of a Page instance
+ with the necessary Page metadata as well as links to let the clients
+ easily navigate the pages. The conversion of a Page to a
+ PagedResources is done by an implementation of the Spring HATEOAS
+ ResourceAssembler interface, the PagedResourcesAssembler.
- public String showUsers(Model model,
- @PageableDefaults(pageNumber = 0, value = 30) Pageable pageable) { … }
-
+
+ Using a PagedResourcesAssembler as controller method
+ argument
+
+ @Controller
+class PersonController {
+
+ @Autowired PersonRepository repository;
+
+ @RequestMapping(value = "/persons", method = RequestMethod.GET)
+ HttpEntity<PagedResources<Person>> persons(Pageable pageable,
+ PagedResourcesAssembler assembler) {
+
+ Page<Person> persons = repository.findAll(pageable);
+ return new ResponseEntity<>(assembler.toResources(persons), HttpStatus.OK);
+ }
+}
+
+
+ Enabling the configuration as shown above allows the
+ PagedResourcesAssembler to be used as
+ controller method argument. Calling
+ toResources(…) on it will cause the
+ following:
+
+
+
+ The content of the Page will
+ become the content of the PagedResources
+ instance.
+
+
+
+ The PagedResources will get a
+ PageMetadata instance attached populated
+ with information form the Page and
+ the underlying PageRequest.
+
+
+
+ The PagedResources gets
+ prev and next links attached depending
+ on the page's state. The links will point to the URI the method
+ invoked is mapped to. The pagination parameters added to the
+ method will match the setup of the
+ PageableHandlerMethodArgumentResolver to
+ make sure the links can be resolved later on.
+
+
+
+ Assume we have 30 Person instances in the
+ database. You can now trigger a request GET
+ http://localhost:8080/persons and you'll see something similar
+ to this:
+
+ { "links" : [ { "rel" : "next",
+ "href" : "http://localhost:8080/persons?page=1&size=20 }
+ ],
+ "content" : [
+ … // 20 Person instances rendered here
+ ],
+ "pageMetadata" : {
+ "size" : 20,
+ "totalElements" : 30,
+ "totalPages" : 2,
+ "number" : 0
+ }
+}You see that the assembler produced the correct URI and also
+ picks up the default configuration present to resolve the parameters
+ into a Pageable for an upcoming
+ request. This means, if you change that configuration, the links will
+ automatically adhere to the change. By default the assembler points to
+ the controller method it was invoked in but that can be customized by
+ handing in a custom Link to be used as base to
+ build the pagination links to overloads of the
+ PagedResourcesAssembler.toResource(…) method.
+
@@ -1218,5 +1241,282 @@ processing.-->The type to which the JSON object will be unmarshalled to will
</beans>
+
+
+ Legacy web support
+
+
+ Domain class web binding for Spring MVC
+
+ Given you are developing a Spring MVC web application you
+ typically have to resolve domain class ids from URLs. By default your
+ task is to transform that request parameter or URL part into the
+ domain class to hand it to layers below then or execute business logic
+ on the entities directly. This would look something like this:
+
+ @Controller
+@RequestMapping("/users")
+public class UserController {
+
+ private final UserRepository userRepository;
+
+ @Autowired
+ public UserController(UserRepository userRepository) {
+ Assert.notNull(repository, "Repository must not be null!");
+ userRepository = userRepository;
+ }
+
+ @RequestMapping("/{id}")
+ public String showUserForm(@PathVariable("id") Long id, Model model) {
+
+ // Do null check for id
+ User user = userRepository.findOne(id);
+ // Do null check for user
+
+ model.addAttribute("user", user);
+ return "user";
+ }
+}
+
+ First you declare a repository dependency for each controller to
+ look up the entity managed by the controller or repository
+ respectively. Looking up the entity is boilerplate as well, as it's
+ always a findOne(…) call. Fortunately Spring
+ provides means to register custom components that allow conversion
+ between a String value to an arbitrary
+ type.
+
+
+ PropertyEditors
+
+ For Spring versions before 3.0 simple Java
+ PropertyEditors had to be used. To
+ integrate with that, Spring Data offers a
+ DomainClassPropertyEditorRegistrar, which
+ looks up all Spring Data repositories registered in the
+ ApplicationContext and registers a
+ custom PropertyEditor for the managed
+ domain class.
+
+ <bean class="….web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
+ <property name="webBindingInitializer">
+ <bean class="….web.bind.support.ConfigurableWebBindingInitializer">
+ <property name="propertyEditorRegistrars">
+ <bean class="org.springframework.data.repository.support.DomainClassPropertyEditorRegistrar" />
+ </property>
+ </bean>
+ </property>
+</bean>
+
+ If you have configured Spring MVC as in the preceding example,
+ you can configure your controller as follows, which reduces a lot of
+ the clutter and boilerplate.
+
+ @Controller
+@RequestMapping("/users")
+public class UserController {
+
+ @RequestMapping("/{id}")
+ public String showUserForm(@PathVariable("id") User user, Model model) {
+
+ model.addAttribute("user", user);
+ return "userForm";
+ }
+}
+
+
+
+ ConversionService
+
+ In Spring 3.0 and later the
+ PropertyEditor support is superseded
+ by a new conversion infrastructure that eliminates the drawbacks of
+ PropertyEditors and uses a stateless
+ X to Y conversion approach. Spring Data now ships with a
+ DomainClassConverter that mimics the behavior
+ of DomainClassPropertyEditorRegistrar. To
+ configure, simply declare a bean instance and pipe the
+ ConversionService being used into its
+ constructor:
+
+ <mvc:annotation-driven conversion-service="conversionService" />
+
+<bean class="org.springframework.data.repository.support.DomainClassConverter">
+ <constructor-arg ref="conversionService" />
+</bean>
+
+ If you are using JavaConfig, you can simply extend Spring
+ MVC's WebMvcConfigurationSupport and hand the
+ FormatingConversionService that the
+ configuration superclass provides into the
+ DomainClassConverter instance you
+ create.
+
+ class WebConfiguration extends WebMvcConfigurationSupport {
+
+ // Other configuration omitted
+
+ @Bean
+ public DomainClassConverter<?> domainClassConverter() {
+ return new DomainClassConverter<FormattingConversionService>(mvcConversionService());
+ }
+}
+
+
+
+
+