diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..ef4f92bc61d330ddcccc06884397c159a080eae5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# SERVER +target/ +.classpath +.project +.settings + +# IDE +.project +.classpath +.settings/ +.idea +*.iws +*.iml +*.ipr + +# Client +goofy-client/.vscode/ + +.attach** +.factorypath diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CreateCommand.java b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CreateCommand.java index f30aa4a4fd334507e96106ddc13d6fd5080262fd..8bd9ac0a50d1347bf4d4c782b563bc0ee81bb587 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CreateCommand.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CreateCommand.java @@ -1,10 +1,11 @@ package de.itvsh.goofy.common.command; +import javax.validation.Valid; + import com.fasterxml.jackson.annotation.JsonIgnore; import de.itvsh.goofy.common.user.UserId; import de.itvsh.goofy.vorgang.RedirectRequest; -import de.itvsh.goofy.wiedervorlage.Wiedervorlage; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; @@ -25,7 +26,6 @@ public class CreateCommand { private String relationId; private CommandOrder order; - private Wiedervorlage body; - + @Valid private RedirectRequest redirectRequest; } \ No newline at end of file diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarCommandController.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarCommandController.java index dfefce30e170a8c61f312b076b36507ffc95fae0..fe926ad2bcd7af3fbdfe44b966e73ca6ee8e6ee3 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarCommandController.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarCommandController.java @@ -13,11 +13,8 @@ import org.springframework.web.bind.annotation.RestController; import de.itvsh.goofy.common.command.CommandController; @RestController -@RequestMapping(KommentarCommandController.KOMMENTAR_COMMANDS) public class KommentarCommandController { - static final String KOMMENTAR_COMMANDS = "/api/kommentars/{kommentarId}/commands"; - @RestController @RequestMapping(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG) public static class KommentarCommandByVorgangController { @@ -33,6 +30,5 @@ public class KommentarCommandController { return ResponseEntity.created(linkTo(CommandController.class).slash(created.getId()).toUri()).build(); } - } } diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarMapper.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..4c1d6ab506f7efa4c615051e03f7d47f0f590e8c --- /dev/null +++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarMapper.java @@ -0,0 +1,18 @@ +package de.itvsh.goofy.kommentar; + +import org.mapstruct.Mapper; +import org.mapstruct.NullValueCheckStrategy; +import org.mapstruct.ReportingPolicy; + +import de.itvsh.ozg.pluto.grpc.command.GrpcCommand; +import de.itvsh.ozg.pluto.kommentar.GrpcKommentar; + +@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) +public interface KommentarMapper { + + GrpcKommentar toGrpcKommentar(Kommentar kommentar); + + Kommentar toKommentar(GrpcKommentar grpcKommentar); + + KommentarCommand toKommentarCommand(GrpcCommand command); +} diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarModelAssembler.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarModelAssembler.java new file mode 100644 index 0000000000000000000000000000000000000000..e8a3b70036bf2c1fba53048bb86734f2be707815 --- /dev/null +++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarModelAssembler.java @@ -0,0 +1,21 @@ +package de.itvsh.goofy.kommentar; + +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; + +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.server.RepresentationModelAssembler; +import org.springframework.stereotype.Component; + +import de.itvsh.goofy.common.ResourceBuilder; + +@Component +class KommentarModelAssembler implements RepresentationModelAssembler<Kommentar, EntityModel<Kommentar>> { + + @Override + public EntityModel<Kommentar> toModel(Kommentar kommentar) { + var selfLink = linkTo(KommentarController.class).slash(kommentar.getId()); + + return ResourceBuilder.fromEntity(kommentar).addLink(selfLink.withSelfRel()) + .buildResource(); + } +} diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarRemoteService.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarRemoteService.java index 2c87c2302a64c08741293bc54aacf5ea4f0e2e85..c9f71236d21ff5ee8b3816eea4060c73f648219f 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarRemoteService.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarRemoteService.java @@ -1,13 +1,37 @@ package de.itvsh.goofy.kommentar; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import de.itvsh.goofy.common.ContextService; +import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse; +import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest; +import de.itvsh.ozg.pluto.grpc.command.GrpcOrder; +import de.itvsh.ozg.pluto.kommentar.KommentarServiceGrpc.KommentarServiceBlockingStub; +import net.devh.boot.grpc.client.inject.GrpcClient; + @Service public class KommentarRemoteService { - public KommentarCommand sendKommentarCommand(String id, KommentarCommand command) { - return null; - // TODO Auto-generated method stub + @GrpcClient("pluto") + private KommentarServiceBlockingStub serviceStub; + @Autowired + private ContextService contextService; + @Autowired + private KommentarMapper mapper; + + public KommentarCommand sendCreateKommentarCommand(String vorgangId, KommentarCommand command) { + GrpcCommandResponse response = serviceStub.createCommand(buildCreateCommandRequest(vorgangId, command)); + + return mapper.toKommentarCommand(response.getCommand()); + } + GrpcCreateCommandRequest buildCreateCommandRequest(String relationId, KommentarCommand command) { + return GrpcCreateCommandRequest.newBuilder() + .setCallContext(contextService.createCallContext()) + .setRelationId(relationId) + .setOrder(GrpcOrder.valueOf(command.getOrder().name())) + .setKommentar(mapper.toGrpcKommentar(command.getKommentar())) + .build(); } } diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarService.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarService.java index a675cf437858282dce927e710dff7a5d501e945f..cbf2e056a6f14aea4fad724d2c6cffb353dcb577 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarService.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarService.java @@ -1,5 +1,7 @@ package de.itvsh.goofy.kommentar; +import javax.validation.Valid; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -11,8 +13,7 @@ public class KommentarService { @Autowired private KommentarRemoteService remoteService; - public KommentarCommand createCreateCommand(String vorgangId, KommentarCommand command) { - return null; - // TODO + public KommentarCommand createCreateCommand(String vorgangId, @Valid KommentarCommand command) { + return remoteService.sendCreateKommentarCommand(vorgangId, command); } } diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/GrpcCommandResponseTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/GrpcCommandResponseTestFactory.java index 09f19b4883b2d3782bbe38116d1f6cbdfa1c3649..cd3f3dac36ef9f96b6bd8317cc669f7e79506833 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/GrpcCommandResponseTestFactory.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/GrpcCommandResponseTestFactory.java @@ -6,6 +6,7 @@ import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse; public class GrpcCommandResponseTestFactory { public static final String COMMAND_ID = CommandTestFactory.ID; + public static final CommandStatus COMMAND_STATUS = CommandStatus.PENDING; public static GrpcCommandResponse create() { return createBuilder().build(); @@ -19,6 +20,7 @@ public class GrpcCommandResponseTestFactory { public static GrpcCommand createGrpcCommand() { return GrpcCommand.newBuilder() .setId(COMMAND_ID) + .setStatus(COMMAND_STATUS.toString()) .build(); } } diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/ApplicationContextTestUtil.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/ApplicationContextTestUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..c3366bb43c99cc7fd38f28438677d462315c0727 --- /dev/null +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/ApplicationContextTestUtil.java @@ -0,0 +1,19 @@ +package de.itvsh.goofy.kommentar; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +@Component +public class ApplicationContextTestUtil { + + @Autowired + private ApplicationContext ctx; + + public void printBeans() { + String[] beansStrings = ctx.getBeanDefinitionNames(); + for (String beanString : beansStrings) + System.out.println(beanString); + } + +} diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/GrpcKommentarTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/GrpcKommentarTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..6064c182ae49773e18bd7a6b57a612bfca5e9041 --- /dev/null +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/GrpcKommentarTestFactory.java @@ -0,0 +1,25 @@ +package de.itvsh.goofy.kommentar; + +import de.itvsh.ozg.pluto.kommentar.GrpcKommentar; + +public class GrpcKommentarTestFactory { + + final static String ID = KommentarTestFactory.ID; + final static String CREATED_BY = KommentarTestFactory.CREATED_BY; + final static String CREATED_BY_NAME = KommentarTestFactory.CREATED_BY_NAME; + final static String CREATED_AT_STR = KommentarTestFactory.CREATED_AT_STR; + final static String TEXT = KommentarTestFactory.TEXT; + + public static GrpcKommentar create() { + return createBuilder().build(); + } + + public static GrpcKommentar.Builder createBuilder() { + return GrpcKommentar.newBuilder() + .setId(ID) + .setCreatedBy(CREATED_BY) + .setCreatedByName(CREATED_BY_NAME) + .setCreatedAt(CREATED_AT_STR) + .setText(TEXT); + } +} diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandTestFactory.java index bef9b85590ba7114488e91c442dabe76ec3cf7e6..0bb86ce34b52b15af01ada1c383079610623b994 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandTestFactory.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandTestFactory.java @@ -13,6 +13,10 @@ public class KommentarCommandTestFactory { return createBuilder().build(); } + public static KommentarCommand create(CommandOrder order) { + return createBuilder().order(order).build(); + } + public static KommentarCommand.KommentarCommandBuilder createBuilder() { return KommentarCommand.builder() .id(ID) diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarMapperTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..379f512ecf1106daa56f4fcdc075dfa559db6642 --- /dev/null +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarMapperTest.java @@ -0,0 +1,49 @@ +package de.itvsh.goofy.kommentar; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; + +class KommentarMapperTest { + + private KommentarMapper mapper = Mappers.getMapper(KommentarMapper.class); + + @Nested + class TestFromGrpc { + + @Test + void shouldMap() { + var kommentar = mapper.toKommentar(GrpcKommentarTestFactory.create()); + + assertThat(kommentar).isNotNull().usingRecursiveComparison().isEqualTo(KommentarTestFactory.create()); + } + + @Test + void shouldHandleNull() { + var grpcKommentar = mapper.toKommentar(null); + + assertThat(grpcKommentar).isNull(); + } + } + + @Nested + class TestToGrpc { + + @Test + void shouldMap() { + var grpcKommentar = mapper.toGrpcKommentar(KommentarTestFactory.createBuilder().id(null).build()); + + assertThat(grpcKommentar).isNotNull().usingRecursiveComparison().ignoringFields("id_", "memoizedHashCode") + .isEqualTo(GrpcKommentarTestFactory.create()); + } + + @Test + void shouldHandleNull() { + var grpcKommentar = mapper.toGrpcKommentar(null); + + assertThat(grpcKommentar).isNull(); + } + } +} diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarRemoteServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarRemoteServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0ec11e0ace09667c9663b8977531961f649a0b5f --- /dev/null +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarRemoteServiceTest.java @@ -0,0 +1,73 @@ +package de.itvsh.goofy.kommentar; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.itvsh.goofy.common.ContextService; +import de.itvsh.goofy.common.command.GrpcCommandResponseTestFactory; +import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; +import de.itvsh.ozg.pluto.grpc.command.GrpcCallContext; +import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse; +import de.itvsh.ozg.pluto.kommentar.KommentarServiceGrpc.KommentarServiceBlockingStub; + +public class KommentarRemoteServiceTest { + + @Spy + @InjectMocks + private KommentarRemoteService service; + + @Spy + private KommentarMapper mapper = Mappers.getMapper(KommentarMapper.class); + @Mock + private KommentarServiceBlockingStub serviceStub; + @Mock + private ContextService contextService; + + @Nested + class TestSendCreateKommentarCommand { + + private GrpcCallContext callContext = GrpcCallContext.newBuilder().build(); + private GrpcCommandResponse response = GrpcCommandResponseTestFactory.createBuilder().build(); + + @BeforeEach + void initTest() { + when(serviceStub.createCommand(any())).thenReturn(response); + when(contextService.createCallContext()).thenReturn(callContext); + } + + @Test + @DisplayName("Should call buildCreateCommandRequest with VorgangId") + void shouldCallCreateRequestWithVorgangId() { + doRequest(); + + verify(service).buildCreateCommandRequest(eq(VorgangHeaderTestFactory.ID), any()); + } + + @Test + void shouldCallStub() { + doRequest(); + + verify(serviceStub).createCommand(any()); + } + + @Test + void shouldMapResult() { + doRequest(); + + verify(mapper).toKommentarCommand(any()); + } + + private void doRequest() { + service.sendCreateKommentarCommand(VorgangHeaderTestFactory.ID, KommentarCommandTestFactory.create()); + } + } +} diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarServiceTest.java index 828017422c52e5c2889d9a4bef3e4225d2d0540e..1a91417046d0a9bde4ea673a3f7f53da3c3db136 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarServiceTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarServiceTest.java @@ -6,6 +6,7 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -22,21 +23,24 @@ public class KommentarServiceTest { @Nested class TestCreateCreateCommand { + @Test void shouldCallRemoteService() { KommentarCommand command = KommentarCommand.builder().order(CREATE_KOMMENTAR).build(); - service.createCreateCommand(KommentarTestFactory.ID, command); + service.createCreateCommand(VorgangHeaderTestFactory.ID, command); - verify(remoteService).sendKommentarCommand(VorgangHeaderTestFactory.ID, command); + verify(remoteService).sendCreateKommentarCommand(VorgangHeaderTestFactory.ID, command); } + @Test void shouldReturnResult() { - KommentarCommand result = KommentarCommand.builder().order(CREATE_KOMMENTAR).build(); - when(remoteService.sendKommentarCommand(anyString(), any())).thenReturn(result); + KommentarCommand resultFromRemoteService = KommentarCommand.builder().order(CREATE_KOMMENTAR) + .id(KommentarCommandTestFactory.ID).build(); + when(remoteService.sendCreateKommentarCommand(anyString(), any())).thenReturn(resultFromRemoteService); - KommentarCommand created = service.createCreateCommand(KommentarCommandTestFactory.ID, KommentarCommandTestFactory.create()); + KommentarCommand resultFromService = service.createCreateCommand(VorgangHeaderTestFactory.ID, KommentarCommandTestFactory.create()); - assertThat(created).isSameAs(result); + assertThat(resultFromService).isSameAs(resultFromRemoteService); } } } diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandITCase.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandITCase.java index 7ca90f4c3110f95903ae0ae49602d4a12306b5ed..509aeb1ecd544158fe0b35ddf439e0944771a3c1 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandITCase.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandITCase.java @@ -18,6 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.ApplicationContext; import org.springframework.http.MediaType; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; @@ -34,6 +35,8 @@ class WiedervorlageCommandITCase { private MockMvc mockMvc; @MockBean private WiedervorlageRemoteService remoteService; + @Autowired + private ApplicationContext ctx; @WithMockUser @Nested diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteServiceTest.java index 2cf74201815cdcade1e676fbf0b0aea13d3ceeb5..948884295f88ccbe3070c0e97104027bad7b121d 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteServiceTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteServiceTest.java @@ -49,7 +49,8 @@ class WiedervorlageRemoteServiceTest { private GrpcFindWiedervorlagesByVorgangRequest request = GrpcFindWiedervorlagesByVorgangRequest.newBuilder() .setVorgangId(VorgangHeaderTestFactory.ID) .build(); - private GrpcFindWiedervorlagesByVorgangResponse response = GrpcFindWiedervorlagesByVorgangResponse.newBuilder().addWiedervorlages(wiedervorlage) + private GrpcFindWiedervorlagesByVorgangResponse response = GrpcFindWiedervorlagesByVorgangResponse.newBuilder() + .addWiedervorlages(wiedervorlage) .addWiedervorlages(wiedervorlage).build(); @BeforeEach @@ -165,7 +166,8 @@ class WiedervorlageRemoteServiceTest { } @Test - void shouldCreatteRequestWithWiedervorlageId() { + @DisplayName("Should call buildCreateCommandRequest with VorgangId") + void shouldCallCreateRequestWithVorgangId() { doRequest(); verify(service).buildCreateCommandRequest(eq(VorgangHeaderTestFactory.ID), any());