Migrate to edison hal library for links

This commit is contained in:
René Pfeuffer
2018-06-05 08:17:25 +02:00
parent 05a9cd115e
commit b25dae00d4
8 changed files with 49 additions and 54 deletions

View File

@@ -154,6 +154,11 @@
<artifactId>resteasy-servlet-initializer</artifactId> <artifactId>resteasy-servlet-initializer</artifactId>
<version>${resteasy.version}</version> <version>${resteasy.version}</version>
</dependency> </dependency>
<dependency>
<groupId>de.otto.edison</groupId>
<artifactId>edison-hal</artifactId>
<version>2.0.0-m2</version>
</dependency>
<!-- injection --> <!-- injection -->

View File

@@ -1,17 +0,0 @@
package sonia.scm.api.v2.resources;
import lombok.Data;
import javax.xml.bind.annotation.XmlRootElement;
import java.net.URI;
@Data
@XmlRootElement
public class Link {
private URI href;
public Link(URI href) {
this.href = href;
}
}

View File

@@ -45,7 +45,7 @@ class LinkBuilder {
return new Parameters(method); return new Parameters(method);
} }
public Link create() { public URI create() {
if (calls.size() < classes.length) { if (calls.size() < classes.length) {
throw new IllegalStateException("not enough methods for all classes"); throw new IllegalStateException("not enough methods for all classes");
} }
@@ -53,7 +53,11 @@ class LinkBuilder {
URI baseUri = uriInfo.getBaseUri(); URI baseUri = uriInfo.getBaseUri();
URI relativeUri = createRelativeUri(); URI relativeUri = createRelativeUri();
URI absoluteUri = baseUri.resolve(relativeUri); URI absoluteUri = baseUri.resolve(relativeUri);
return new Link(absoluteUri); return absoluteUri;
}
public String href() {
return create().toString();
} }
private LinkBuilder add(String method, String[] parameters) { private LinkBuilder add(String method, String[] parameters) {

View File

@@ -1,5 +1,6 @@
package sonia.scm.api.v2.resources; package sonia.scm.api.v2.resources;
import de.otto.edison.hal.Links;
import org.apache.shiro.SecurityUtils; import org.apache.shiro.SecurityUtils;
import org.mapstruct.*; import org.mapstruct.*;
import sonia.scm.api.rest.resources.UserResource; import sonia.scm.api.rest.resources.UserResource;
@@ -8,10 +9,11 @@ import sonia.scm.user.User;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
import java.time.Instant; import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import static de.otto.edison.hal.Link.link;
import static de.otto.edison.hal.Links.linkingTo;
@Mapper @Mapper
public abstract class User2UserDtoMapper { public abstract class User2UserDtoMapper {
@@ -26,14 +28,17 @@ public abstract class User2UserDtoMapper {
void appendLinks(@MappingTarget UserDto target, @Context UriInfo uriInfo) { void appendLinks(@MappingTarget UserDto target, @Context UriInfo uriInfo) {
LinkBuilder userLinkBuilder = new LinkBuilder(uriInfo, UserV2Resource.class, UserSubResource.class); LinkBuilder userLinkBuilder = new LinkBuilder(uriInfo, UserV2Resource.class, UserSubResource.class);
LinkBuilder collectionLinkBuilder = new LinkBuilder(uriInfo, UserV2Resource.class, UserCollectionResource.class); LinkBuilder collectionLinkBuilder = new LinkBuilder(uriInfo, UserV2Resource.class, UserCollectionResource.class);
Map<String, Link> links = new HashMap<>();
links.put("self", userLinkBuilder.method("getUserSubResource").parameters(target.getName()).method("get").parameters().create()); Links.Builder linksBuilder = linkingTo()
.self(userLinkBuilder.method("getUserSubResource").parameters(target.getName()).method("get").parameters().href());
if (SecurityUtils.getSubject().hasRole(Role.ADMIN)) { if (SecurityUtils.getSubject().hasRole(Role.ADMIN)) {
links.put("delete", userLinkBuilder.method("getUserSubResource").parameters(target.getName()).method("delete").parameters().create()); linksBuilder
links.put("update", userLinkBuilder.method("getUserSubResource").parameters(target.getName()).method("update").parameters().create()); .single(link("delete", userLinkBuilder.method("getUserSubResource").parameters(target.getName()).method("delete").parameters().href()))
links.put("create", collectionLinkBuilder.method("getUserCollectionResource").parameters().method("create").parameters().create()); .single(link("update", userLinkBuilder.method("getUserSubResource").parameters(target.getName()).method("update").parameters().href()))
.single(link("create", collectionLinkBuilder. method("getUserCollectionResource").parameters().method("create").parameters().href()));
} }
target.setLinks(links); target.add(
linksBuilder.build());
} }
@Mapping(target = "creationDate") @Mapping(target = "creationDate")

View File

@@ -76,7 +76,7 @@ public class UserCollectionResource extends AbstractManagerResource<User, UserEx
manager.create(user); manager.create(user);
LinkBuilder builder = new LinkBuilder(uriInfo, UserV2Resource.class, UserSubResource.class); LinkBuilder builder = new LinkBuilder(uriInfo, UserV2Resource.class, UserSubResource.class);
return Response.created(builder.method("getUserSubResource").parameters(user.getName()).method("get").parameters().create().getHref()).build(); return Response.created(builder.method("getUserSubResource").parameters(user.getName()).method("get").parameters().create()).build();
} }
@Override @Override

View File

@@ -1,17 +1,17 @@
package sonia.scm.api.v2.resources; package sonia.scm.api.v2.resources;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import de.otto.edison.hal.HalRepresentation;
import de.otto.edison.hal.Links;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.time.Instant; import java.time.Instant;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
@Data @AllArgsConstructor @NoArgsConstructor @Data @AllArgsConstructor @NoArgsConstructor
public class UserDto { public class UserDto extends HalRepresentation {
private boolean active; private boolean active;
private boolean admin; private boolean admin;
private Instant creationDate; private Instant creationDate;
@@ -23,6 +23,8 @@ public class UserDto {
private String password; private String password;
private String type; private String type;
@JsonProperty("_links") @Override
private Map<String, Link> links; protected HalRepresentation add(Links links) {
return super.add(links);
}
} }

View File

@@ -46,8 +46,7 @@ public class LinkBuilderTest {
URI actual = builder URI actual = builder
.method("sub") .method("sub")
.parameters("param_x") .parameters("param_x")
.create() .create();
.getHref();
assertEquals("http://example.com/base/main/param_x", actual.toString()); assertEquals("http://example.com/base/main/param_x", actual.toString());
} }
@@ -55,13 +54,12 @@ public class LinkBuilderTest {
public void shouldBuildPathOverSubResources() { public void shouldBuildPathOverSubResources() {
LinkBuilder builder = new LinkBuilder(uriInfo, Main.class, Sub.class); LinkBuilder builder = new LinkBuilder(uriInfo, Main.class, Sub.class);
URI actual = builder URI actual = builder
.method("sub") .method("sub")
.parameters("param_x") .parameters("param_x")
.method("x") .method("x")
.parameters("param_y", "param_z") .parameters("param_y", "param_z")
.create() .create();
.getHref();
assertEquals("http://example.com/base/main/param_x/sub/param_y/param_z", actual.toString()); assertEquals("http://example.com/base/main/param_x/sub/param_y/param_z", actual.toString());
} }
@@ -72,8 +70,7 @@ public class LinkBuilderTest {
URI actual = builder URI actual = builder
.method("get") .method("get")
.parameters() .parameters()
.create() .create();
.getHref();
assertEquals("http://example.com/base", actual.toString()); assertEquals("http://example.com/base", actual.toString());
} }

View File

@@ -15,7 +15,7 @@ import java.net.URISyntaxException;
import java.time.Instant; import java.time.Instant;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -26,13 +26,12 @@ public class User2UserDtoMapperTest {
private final Subject subject = mock(Subject.class); private final Subject subject = mock(Subject.class);
private ThreadState subjectThreadState = new SubjectThreadState(subject); private ThreadState subjectThreadState = new SubjectThreadState(subject);
private URI baseUri; private URI expectedBaseUri;
private URI expextedBaseUri;
@Before @Before
public void init() throws URISyntaxException { public void init() throws URISyntaxException {
baseUri = new URI("http://example.com/base/"); URI baseUri = new URI("http://example.com/base/");
expextedBaseUri = baseUri.resolve(UserV2Resource.USERS_PATH_V2 + "/"); expectedBaseUri = baseUri.resolve(UserV2Resource.USERS_PATH_V2 + "/");
when(uriInfo.getBaseUri()).thenReturn(baseUri); when(uriInfo.getBaseUri()).thenReturn(baseUri);
subjectThreadState.bind(); subjectThreadState.bind();
} }
@@ -44,10 +43,10 @@ public class User2UserDtoMapperTest {
UserDto userDto = mapper.userToUserDto(user, uriInfo); UserDto userDto = mapper.userToUserDto(user, uriInfo);
assertEquals("expected map with self baseUri", expextedBaseUri.resolve("abc"), userDto.getLinks().get("self").getHref()); assertEquals("expected self link", expectedBaseUri.resolve("abc").toString(), userDto.getLinks().getLinkBy("self").get().getHref());
assertEquals("expected map with delete baseUri", expextedBaseUri.resolve("abc"), userDto.getLinks().get("delete").getHref()); assertEquals("expected delete link", expectedBaseUri.resolve("abc").toString(), userDto.getLinks().getLinkBy("delete").get().getHref());
assertEquals("expected map with update baseUri", expextedBaseUri.resolve("abc"), userDto.getLinks().get("update").getHref()); assertEquals("expected update link", expectedBaseUri.resolve("abc").toString(), userDto.getLinks().getLinkBy("update").get().getHref());
assertEquals("expected map with create baseUri", expextedBaseUri, userDto.getLinks().get("create").getHref()); assertEquals("expected create link", expectedBaseUri.toString(), userDto.getLinks().getLinkBy("create").get().getHref());
} }
private User createDefaultUser() { private User createDefaultUser() {
@@ -64,10 +63,10 @@ public class User2UserDtoMapperTest {
UserDto userDto = mapper.userToUserDto(user, uriInfo); UserDto userDto = mapper.userToUserDto(user, uriInfo);
assertEquals("expected map with self baseUri", expextedBaseUri.resolve("abc"), userDto.getLinks().get("self").getHref()); assertEquals("expected self link", expectedBaseUri.resolve("abc").toString(), userDto.getLinks().getLinkBy("self").get().getHref());
assertNull("expected map without delete baseUri", userDto.getLinks().get("delete")); assertFalse("expected no delete link", userDto.getLinks().getLinkBy("delete").isPresent());
assertNull("expected map without update baseUri", userDto.getLinks().get("update")); assertFalse("expected no update link", userDto.getLinks().getLinkBy("update").isPresent());
assertNull("expected map without create baseUri", userDto.getLinks().get("create")); assertFalse("expected no create link", userDto.getLinks().getLinkBy("create").isPresent());
} }
@Test @Test