From c62168274de411da1ea2e4863cd2ed9ffbe738be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 1 Jun 2018 14:19:12 +0200 Subject: [PATCH] Use Instant in DTO --- scm-webapp/pom.xml | 11 ++++++++++- .../sonia/scm/api/rest/JSONContextResolver.java | 7 ++++++- .../api/v2/resources/User2UserDtoMapper.java | 11 +++++++---- .../sonia/scm/api/v2/resources/UserDto.java | 5 +++-- .../api/v2/resources/UserDto2UserMapper.java | 11 +++++++---- .../v2/resources/User2UserDtoMapperTest.java | 16 ++++++++++++++++ .../v2/resources/UserDto2UserMapperTest.java | 17 +++++++++++++++++ 7 files changed, 66 insertions(+), 12 deletions(-) diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index 43c30ef465..b681e5c5e8 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -107,7 +107,16 @@ jackson-jaxrs-base ${jackson.version} - + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + ${jackson.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/JSONContextResolver.java b/scm-webapp/src/main/java/sonia/scm/api/rest/JSONContextResolver.java index 30602f5716..9ea7acb00a 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/JSONContextResolver.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/JSONContextResolver.java @@ -36,7 +36,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import com.fasterxml.jackson.databind.type.TypeFactory; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector; + import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.ext.ContextResolver; @@ -55,7 +58,9 @@ public final class JSONContextResolver implements ContextResolver private final ObjectMapper mapper; public JSONContextResolver() { - mapper = new ObjectMapper(); + mapper = new ObjectMapper() + .registerModule(new Jdk8Module()) + .registerModule(new JavaTimeModule()); mapper.setAnnotationIntrospector(createAnnotationIntrospector()); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/User2UserDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/User2UserDtoMapper.java index 3a8caa437d..c2bce60820 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/User2UserDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/User2UserDtoMapper.java @@ -1,15 +1,13 @@ package sonia.scm.api.v2.resources; import org.apache.shiro.SecurityUtils; -import org.mapstruct.AfterMapping; -import org.mapstruct.Context; -import org.mapstruct.Mapper; -import org.mapstruct.MappingTarget; +import org.mapstruct.*; import sonia.scm.api.rest.resources.UserResource; import sonia.scm.security.Role; import sonia.scm.user.User; import javax.ws.rs.core.UriInfo; +import java.time.Instant; import java.util.HashMap; import java.util.Map; @@ -36,4 +34,9 @@ public abstract class User2UserDtoMapper { } target.setLinks(links); } + + @Mappings({@Mapping(target = "lastModified"), @Mapping(target = "creationDate")}) + Instant mapTime(Long epochMilli) { + return epochMilli == null? null: Instant.ofEpochMilli(epochMilli); + } } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserDto.java index e3970e86af..9bd42d0a87 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserDto.java @@ -3,15 +3,16 @@ package sonia.scm.api.v2.resources; import lombok.Data; import javax.xml.bind.annotation.XmlElement; +import java.time.Instant; import java.util.Map; @Data public class UserDto { private boolean active; private boolean admin; - private Long creationDate; + private Instant creationDate; private String displayName; - private Long lastModified; + private Instant lastModified; private String mail; private String name; private String password; diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserDto2UserMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserDto2UserMapper.java index 391799f00e..30b0f16e82 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserDto2UserMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserDto2UserMapper.java @@ -2,12 +2,11 @@ package sonia.scm.api.v2.resources; import com.google.inject.Inject; import org.apache.shiro.authc.credential.PasswordService; -import org.mapstruct.Context; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.Named; +import org.mapstruct.*; import sonia.scm.user.User; +import java.time.Instant; + import static sonia.scm.api.rest.resources.UserResource.DUMMY_PASSWORT; @Mapper @@ -30,6 +29,10 @@ public abstract class UserDto2UserMapper { { return passwordService.encryptPassword(password); } + } + @Mappings({@Mapping(target = "lastModified"), @Mapping(target = "creationDate")}) + Long mapTime(Instant instant) { + return instant == null? null: instant.toEpochMilli(); } } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/User2UserDtoMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/User2UserDtoMapperTest.java index 65a5dd8f50..63a82520cb 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/User2UserDtoMapperTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/User2UserDtoMapperTest.java @@ -12,6 +12,7 @@ import sonia.scm.user.User; import javax.ws.rs.core.UriInfo; import java.net.URI; import java.net.URISyntaxException; +import java.time.Instant; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @@ -84,4 +85,19 @@ public class User2UserDtoMapperTest { assertEquals(UserResource.DUMMY_PASSWORT, userDto.getPassword()); } + + @Test + public void shouldMapTimes() { + User user = new User(); + user.setName("abc"); + Instant expectedCreationDate = Instant.ofEpochSecond(6666666); + Instant expectedModificationDate = expectedCreationDate.plusSeconds(1); + user.setCreationDate(expectedCreationDate.toEpochMilli()); + user.setLastModified(expectedModificationDate.toEpochMilli()); + + UserDto userDto = mapper.userToUserDto(user, uriInfo); + + assertEquals(expectedCreationDate, userDto.getCreationDate()); + assertEquals(expectedModificationDate, userDto.getLastModified()); + } } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserDto2UserMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserDto2UserMapperTest.java index 788ec0d64e..08b9fe604f 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserDto2UserMapperTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserDto2UserMapperTest.java @@ -7,6 +7,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import sonia.scm.user.User; +import java.time.Instant; + import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; @@ -36,6 +38,21 @@ public class UserDto2UserMapperTest { assertEquals("encrypted" , user.getPassword()); } + @Test + public void shouldMapTimes() { + UserDto dto = new UserDto(); + dto.setName("abc"); + Instant expectedCreationDate = Instant.ofEpochMilli(66666660000L); + Instant expectedModificationDate = null; + dto.setCreationDate(expectedCreationDate); + dto.setLastModified(expectedModificationDate); + + User user = mapper.userDtoToUser(dto, "original password"); + + assertEquals((Long) expectedCreationDate.toEpochMilli(), user.getCreationDate()); + assertEquals(null, user.getLastModified()); + } + @Before public void init() { initMocks(this);