DATAREST-48 Fix a bug with compact content-type not displaying links properly when executing query methods.

This commit is contained in:
Jon Brisbin
2012-09-13 08:22:57 -05:00
committed by Jon Brisbin
parent 5bc83602f4
commit 2ddf788350
3 changed files with 49 additions and 31 deletions

45
doc/changing_json.md Normal file
View File

@@ -0,0 +1,45 @@
# Customizing the JSON output
Sometimes in your application you need to provide links to other resources from a particular entity. For example, a
`Customer` response might be enriched with links to a current shopping cart, or links to manage resources related to
that entity. Spring Data REST provides integration with [Spring HATEOAS](https://github.com/SpringSource/spring-hateoas)
and provides an extension hook for users to alter the representation of resources going out to the client.
### The ResourceProcessor interface
Spring HATEOAS defines a `ResourceProcessor<?>` interface for processing entities. All beans of type
`ResourceProcessor<Resource<T>>` will be automatically picked up by the Spring Data REST exporter and triggered when
serializing an entity of type `T`. For example, to define a processor for a `Person` entity, add a `@Bean` to your
ApplicationContext like the following (which is taken from the Spring Data REST tests):
@Bean public ResourceProcessor<Resource<Person>> personProcessor() {
return new ResourceProcessor<Resource<Person>>() {
@Override public Resource<Person> process(Resource<Person> resource) {
resource.add(new Link("http://localhost:8080/people", "added-link"));
return resource;
}
};
}
### Adding Links
It's possible to add links to the default representation of an entity by simply calling `resource.add(Link)` like the
example above. Any links you add to the `Resource` will be added to the final output.
### Customizing the representation
The Spring Data REST exporter executes any discovered `ResourceProcessor`s before it creates the output representation.
It does this by registering a `Converter<Entity, Resource>` instance with an internal `ConversionService`. This is the
component responsible for creating the links to referenced entities (e.g. those objects under the "links" property in
the object's JSON representation). It takes an `@Entity` and iterates over its properties, creating links for those
properties that are managed by a `Repository` and copying across any embedded or simple properties.
If your project needs to have output in a different format, however, it's possible to completely replace the default
outgoing JSON representation with your own. If you register your own `ConversionService` in the ApplicationContext and
register your own `Converter<Person, Resource>`, then you can return a `Resource` implementation of your choosing.
For example, to rename the "links" property to "_links", create your own `Resource` subclass that renames the
property using Jackson's `@JsonProperty` annotation:
public class MyResource extends Resource

View File

@@ -1,6 +1,6 @@
# Handling ApplicationEvents in the REST Exporter
There are eight different events that the REST exporter emits throughout the process of working with an entity. Those are:
There are six different events that the REST exporter emits throughout the process of working with an entity. Those are:
* BeforeSaveEvent
* AfterSaveEvent
@@ -8,8 +8,6 @@ There are eight different events that the REST exporter emits throughout the pro
* AfterLinkSaveEvent
* BeforeDeleteEvent
* AfterDeleteEvent
* BeforeRenderResourcesEvent
* BeforeRenderResourceEvent
### ApplicationListener
@@ -110,28 +108,3 @@ You can pass the base package of the packages you want searched for handlers in
<bean class="org.springframework.data.rest.repository.context.AnnotatedHandlerRepositoryEventListener">
<property name="basePackage" value="com.mycompany.repository.handlers"/>
</bean>
### Handling Render events
It's possible to alter the representation of the resource that gets sent back to the client. There are two possible reponses: a `org.springframework.data.rest.core.Resources` bean, which has a `content` and `links` property. The `content` property is a list of `org.springframework.data.rest.core.Resource` objects. In the case of JPA @Entities, these will actually be the `org.springframework.data.rest.core.MapResource` subclass of `Resource`. These helpers are what are run through the JSON mapper and used to produce the output sent to the client.
If, for example, you want to add links to the representation for a `Person`, you could define a POJO class and annotate it with `@RepositoryEventHandler(Person.class)` just like in the above example. Then you could define a couple of methods for altering the representations of the `Resources` and `Resource` objects that are sent to the client.
The `org.springframework.data.rest.core.Resources` bean is sent to the client whenever lists or results are required. If you call a query method or ask for a list of entities, then the `Resources` response is the one you'll get. If you ask for a specific entity's representation, however, you'll want to alter the plain `org.springframework.data.rest.core.Resource` bean.
An example handler class for these would look something like this:
@RepositoryEventHandler(Person.class)
public class PersonRenderHandler {
@HandleBeforeRenderResources
public void handleBeforeRenderResources(ServerHttpRequest request, RepositoryMetadata repoMeta, Resources resources) {
resources.addLink(new SimpleLink("linkAddedByHandler", new URI("http://localhost:8080/linkAddedByHandler"));
}
@HandleBeforeRenderResource
public void handleBeforeRenderResource(ServerHttpRequest request, RepositoryMetadata repoMeta, Resource resource) {
resource.addLink(new SimpleLink("linkAddedByHandler", new URI("http://localhost:8080/linkAddedByHandler"));
}
}

View File

@@ -641,7 +641,7 @@ public class RepositoryRestController
new Resources<String>(Collections.<String>emptyList()));
}
Set<Link> links = new HashSet<Link>();
List<Link> links = new ArrayList<Link>();
PagedResources.PageMetadata pageMetadata = null;
Iterator entities = Collections.emptyList().iterator();
@@ -717,8 +717,8 @@ public class RepositoryRestController
HttpStatus.OK,
new HttpHeaders(),
(null != pageMetadata
? new PagedResources(results, pageMetadata)
: new Resources(results)));
? new PagedResources(results, pageMetadata, links)
: new Resources(results, links)));
}
/**