Skip to content

Commit

Permalink
Add support for fully-qualified links
Browse files Browse the repository at this point in the history
- also make the linkrel configurable
Fixes #148
  • Loading branch information
Paul Warren committed Mar 11, 2020
1 parent 53c1e4f commit ca7edff
Show file tree
Hide file tree
Showing 24 changed files with 1,194 additions and 529 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class ContentRestAutoConfiguration {
public static class ContentRestProperties {

private URI baseUri;
private boolean fullyQualifiedLinks = false;

public URI getBaseUri() {
return baseUri;
Expand All @@ -30,7 +31,15 @@ public URI getBaseUri() {
public void setBaseUri(URI baseUri) {
this.baseUri = baseUri;
}
}

public boolean fullyQualifiedLinks() {
return this.fullyQualifiedLinks;
}

public void setFullyQualifiedLinks(boolean fullyQualifiedLinks) {
this.fullyQualifiedLinks = fullyQualifiedLinks;
}
}

@Bean
public SpringBootContentRestConfigurer springBootContentRestConfigurer() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ public SpringBootContentRestConfigurer(ContentRestProperties properties) {
@Override
public void configure(RestConfiguration config) {

if (properties == null || properties.getBaseUri() == null)
if (properties == null) {
return;
}

config.setBaseUri(properties.getBaseUri());
if (properties.getBaseUri() != null) {
config.setBaseUri(properties.getBaseUri());
}

config.setFullyQualifiedLinks(properties.fullyQualifiedLinks());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,22 @@ public class ContentRestAutoConfigurationTest {
});
});

Context("given an environment specifying a base uri", () -> {
Context("given an environment specifying rest properties", () -> {
BeforeEach(() -> {
System.setProperty("spring.content.rest.base-uri", "/contentApi");
System.setProperty("spring.content.rest.content-links", "false");
});
AfterEach(() -> {
System.clearProperty("spring.content.rest.base-uri");
});
It("should have a filesystem properties bean with the correct root set", () -> {
It("should have a filesystem properties bean with the correct properties set", () -> {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(TestConfig.class);
context.setServletContext(new MockServletContext());
context.refresh();

assertThat(context.getBean(ContentRestAutoConfiguration.ContentRestProperties.class).getBaseUri(),
is(URI.create("/contentApi")));
assertThat(context.getBean(ContentRestAutoConfiguration.ContentRestProperties.class).getBaseUri(), is(URI.create("/contentApi")));
assertThat(context.getBean(ContentRestAutoConfiguration.ContentRestProperties.class).fullyQualifiedLinks(), is(false));

assertThat(context.getBean(SpringBootContentRestConfigurer.class), is(not(nullValue())));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import static com.github.paulcwarren.ginkgo4j.Ginkgo4jDSL.Describe;
import static com.github.paulcwarren.ginkgo4j.Ginkgo4jDSL.It;
import static com.github.paulcwarren.ginkgo4j.Ginkgo4jDSL.JustBeforeEach;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -56,6 +57,17 @@ public class SpringBootContentRestConfigurerTest {
});
});

Context("given a fullyQualifiedLinks property setting", () -> {

BeforeEach(() -> {
properties.setFullyQualifiedLinks(true);
});

It("should set the property on the RestConfiguration", () -> {
verify(restConfig).setFullyQualifiedLinks(eq(true));
});
});

Context("given a null base uri property", () -> {

It("should not set the property on the RestConfiguration", () -> {
Expand All @@ -71,6 +83,7 @@ public class SpringBootContentRestConfigurerTest {

It("should not set the property on the RestConfiguration", () -> {
verify(restConfig, never()).setBaseUri(anyObject());
verify(restConfig, never()).setFullyQualifiedLinks(anyBoolean());
});
});
});
Expand Down
1 change: 1 addition & 0 deletions spring-content-rest/src/main/asciidoc/rest-baseuri.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ class CustomContentRestMvcConfiguration {
}
----
====

104 changes: 104 additions & 0 deletions spring-content-rest/src/main/asciidoc/rest-fullyqualifiedlinks.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
== Fully Qualified Links
By default, and where possible, Spring Content REST exports Spring Resources to shortened link URIs. These will often
match the Spring Data Rest Entity URI.

Given the following example:

====
[source, java]
----
@Entity
public class Dvd {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ContentId
private UUID contentId;
@ContentLength
private Long contentLength;
@MimeType
private String mimeType;
// getters and setters
}
public interface DvdRepository extends CrudRepository<Dvd, Long> {}
public interface DvdStore extends ContentStore<Dvd, UUID> {}
----
====

As there is only a single associated Spring Resource, Spring Content REST will generate the following URI:

====
[source, java]
----
"_links" : {
"self" : {
...
},
"dvd" : {
...
},
"dvds" : {
"href" : "http://localhost:8080/dvds/1"
}
}
----
====

To generate fully qualified link URIs set the following property:

====
[source, java]
----
spring.content.rest.fullyQualifiedLinks=true
----
====

Or if you are not using Spring Boot, you can do the following:

====
[source, java]
----
@Configuration
class CustomContentRestMvcConfiguration {
@Bean
public ContentRestConfigurer contentRestConfigurer() {
return new ContentRestConfigurer() {
@Override
public void configure(RestConfiguration config) {
config.setFullyQualifiedLinks(true);
}
};
}
}
----
====

Spring Content REST will now generate links as follows:

====
[source, java]
----
"_links" : {
"self" : {
...
},
"dvd" : {
...
},
"content" : {
"href" : "http://localhost:8080/dvds/1/content"
}
}
----
====

where `content` is the extracted property name taken from the field `contentId`.
2 changes: 2 additions & 0 deletions spring-content-rest/src/main/asciidoc/rest-index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ include::{spring-versions-jpa-docs}/jpaversions-rest.adoc[leveloffset=+1]
include::rest-cors.adoc[leveloffset=+1]

include::rest-baseuri.adoc[leveloffset=+1]
include::rest-linkrel.adoc[leveloffset=+1]
include::rest-fullyqualifiedlinks.adoc[leveloffset=+1]
//[[appendix]]
//= Appendix

Expand Down
83 changes: 83 additions & 0 deletions spring-content-rest/src/main/asciidoc/rest-linkrel.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
== Changing the link relation

For each exported Spring Resource, Spring Content REST will generate a suitable linkrel.

However, it can sometimes be useful to control this yourself.

Given the following example:

====
[source, java]
----
@Entity
public class Dvd {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ContentId
private UUID contentId;
@ContentLength
private Long contentLength;
@MimeType
private String mimeType;
// getters and setters
}
public interface DvdRepository extends CrudRepository<Dvd, Long> {}
public interface DvdStore extends ContentStore<Dvd, UUID> {}
----
====

Spring Content REST will export the Spring Resource to the following linkrel:

====
[source, java]
----
"_links" : {
"self" : {
...
},
"dvd" : {
...
},
"dvds" : {
"href" : "http://localhost:8080/dvds/1"
}
}
----
====

Specifying a `linkRel` on the StoreRestResource, as follows:

====
[source, java]
----
@StoreRestResource(linkRel="content")
public interface DvdStore extends ContentStore<Dvd, UUID> {}
----
====

will result in the following linkrel instead:

====
[source, java]
----
"_links" : {
"self" : {
...
},
"dvd" : {
...
},
"content" : {
"href" : "http://localhost:8080/dvds/1"
}
}
----
====

Loading

0 comments on commit ca7edff

Please sign in to comment.