#185 - Traverson can now get LinkDiscoverers configured.

Moved to a setter based configuration for both the RestOperations and LinkDiscoverers to be used.

Related pull request: #189.
This commit is contained in:
Oliver Gierke
2014-07-08 20:40:21 +02:00
parent c1e940c5f3
commit a363122be9
4 changed files with 87 additions and 20 deletions

View File

@@ -93,7 +93,15 @@ class Rels {
*/
@Override
public Link findInResponse(String response, MediaType mediaType) {
return discoverers.getLinkDiscovererFor(mediaType).findLinkWithRel(rel, response);
LinkDiscoverer discoverer = discoverers.getLinkDiscovererFor(mediaType);
if (discoverer == null) {
throw new IllegalStateException(String.format("Did not find LinkDiscoverer supporting media type %s!",
mediaType));
}
return discoverer.findLinkWithRel(rel, response);
}
}

View File

@@ -62,11 +62,19 @@ import com.jayway.jsonpath.JsonPath;
*/
public class Traverson {
private static final LinkDiscoverers DEFAULT_LINK_DISCOVERERS;
static {
LinkDiscoverer discoverer = new HalLinkDiscoverer();
DEFAULT_LINK_DISCOVERERS = new LinkDiscoverers(OrderAwarePluginRegistry.create(Arrays.asList(discoverer)));
}
private final URI baseUri;
private final RestOperations operations;
private final LinkDiscoverers discoverers;
private final List<MediaType> mediaTypes;
private RestOperations operations;
private LinkDiscoverers discoverers;
/**
* Creates a new {@link Traverson} interacting with the given base URI and using the given {@link MediaType}s to
* interact with the service.
@@ -75,29 +83,15 @@ public class Traverson {
* @param mediaType must not be {@literal null} or empty.
*/
public Traverson(URI baseUri, MediaType... mediaTypes) {
this(null, baseUri, mediaTypes);
}
/**
* Creates a new {@link Traverson} with custom rest operations, interacting with the given base URI and using the
* given {@link MediaType}s to interact with the service. The custom rest operations will be prepared with message
* converters for the given media types.
*
* @param operations allowing to customize the http requests with interceptors, client configurations etc.
* @param baseUri must not be {@literal null}.
* @param mediaType must not be {@literal null} or empty.
*/
public Traverson(RestOperations operations, URI baseUri, MediaType... mediaTypes) {
Assert.notNull(baseUri, "Base URI must not be null!");
Assert.notEmpty(mediaTypes, "At least one media type must be given!");
this.mediaTypes = Arrays.asList(mediaTypes);
this.baseUri = baseUri;
this.operations = operations == null ? createDefaultTemplate(this.mediaTypes) : operations;
this.discoverers = DEFAULT_LINK_DISCOVERERS;
LinkDiscoverer discoverer = new HalLinkDiscoverer();
this.discoverers = new LinkDiscoverers(OrderAwarePluginRegistry.create(Arrays.asList(discoverer)));
setRestOperations(createDefaultTemplate(this.mediaTypes));
}
private static final RestOperations createDefaultTemplate(List<MediaType> mediaTypes) {
@@ -134,6 +128,34 @@ public class Traverson {
return converter;
}
/**
* Configures the {@link RestOperations} to use. If {@literal null} is provided a default {@link RestTemplate} will be
* used.
*
* @param operations
* @return
*/
public Traverson setRestOperations(RestOperations operations) {
this.operations = operations == null ? createDefaultTemplate(mediaTypes) : operations;
return this;
}
/**
* Sets the {@link LinkDiscoverers} to use. By default a single {@link HalLinkDiscoverer} is registered. If
* {@literal null} is provided the default is reapplied.
*
* @param discoverer can be {@literal null}.
* @return
*/
public Traverson setLinkDiscoverers(List<? extends LinkDiscoverer> discoverer) {
this.discoverers = discoverers == null ? DEFAULT_LINK_DISCOVERERS : new LinkDiscoverers(
OrderAwarePluginRegistry.create(discoverer));
return this;
}
/**
* Sets up a {@link TraversalBuilder} to follow the given rels.
*

View File

@@ -30,6 +30,7 @@ import org.springframework.hateoas.Resource;
import org.springframework.hateoas.Resources;
import org.springframework.hateoas.core.EvoInflectorRelProvider;
import org.springframework.hateoas.hal.Jackson2HalModule;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -66,6 +67,20 @@ public class Server implements Closeable {
havingPathEqualTo("/"). //
respond(). //
withBody("");
// For GitHubLinkDiscoverer tests
onRequest(). //
havingPathEqualTo("/github"). //
respond(). //
withBody("{ \"foo_url\" : \"" + rootResource() + "/github/4711\"}"). //
withContentType(MediaType.APPLICATION_JSON_VALUE);
onRequest(). //
havingPathEqualTo("/github/4711"). //
respond(). //
withBody("{ \"key\" : \"value\"}"). //
withContentType(MediaType.APPLICATION_JSON_VALUE);
}
public String rootResource() {

View File

@@ -30,6 +30,7 @@ import org.springframework.core.ParameterizedTypeReference;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.Resource;
import org.springframework.hateoas.core.JsonPathLinkDiscoverer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.MediaType;
@@ -176,12 +177,26 @@ public class TraversonTests {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(Arrays.<ClientHttpRequestInterceptor> asList(interceptor));
this.traverson = new Traverson(restTemplate, baseUri, MediaTypes.HAL_JSON);
this.traverson = new Traverson(baseUri, MediaTypes.HAL_JSON);
this.traverson.setRestOperations(restTemplate);
traverson.follow("movies", "movie", "actor").<String> toObject("$.name");
assertThat(interceptor.intercepted, is(4));
}
/**
* @see #185
*/
@Test
public void usesCustomLinkDiscoverer() {
this.traverson = new Traverson(URI.create(server.rootResource() + "/github"), MediaType.APPLICATION_JSON);
this.traverson.setLinkDiscoverers(Arrays.asList(new GitHubLinkDiscoverer()));
String value = this.traverson.follow("foo").toObject("$.key");
assertThat(value, is("value"));
}
private void setUpActors() {
Resource<Actor> actor = new Resource<Actor>(new Actor("Keanu Reaves"));
@@ -206,4 +221,11 @@ public class TraversonTests {
return execution.execute(request, body);
}
};
static class GitHubLinkDiscoverer extends JsonPathLinkDiscoverer {
public GitHubLinkDiscoverer() {
super("$.%s_url", MediaType.APPLICATION_JSON);
}
}
}