diff --git a/router/src/main/java/de/ozgcloud/eingang/router/ClosableStub.java b/router/src/main/java/de/ozgcloud/eingang/router/ClosableStub.java index 2f85a16cf1840901b66addcb92bf12f86cefa632..5f24838b97067eda3f3ecc29246b715223ecf47d 100644 --- a/router/src/main/java/de/ozgcloud/eingang/router/ClosableStub.java +++ b/router/src/main/java/de/ozgcloud/eingang/router/ClosableStub.java @@ -2,29 +2,24 @@ package de.ozgcloud.eingang.router; import java.util.Objects; import java.util.concurrent.TimeUnit; -import java.util.function.Function; import de.ozgcloud.eingang.common.errorhandling.TechnicalException; import io.grpc.ManagedChannel; +import io.grpc.stub.AbstractStub; import lombok.Builder; import lombok.Getter; -@Getter @Builder -class ClosableStub<T> implements ManagableStub<T> { +@Getter +class ClosableStub<T extends AbstractStub<?>> implements ManagableStub<T> { private static final int SHUTDOWM_TIME = 10; - private ManagedChannel channel; - private Function<ManagedChannel, T> createFunction; - private T stub; + private ManagedChannel channel; @Override public T get() { - if (Objects.isNull(stub)) { - stub = createFunction.apply(channel); - } return stub; } @@ -39,6 +34,7 @@ class ClosableStub<T> implements ManagableStub<T> { try { channel.shutdown().awaitTermination(ClosableStub.SHUTDOWM_TIME, TimeUnit.SECONDS); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw new TechnicalException("Error shutting down grpc channel.", e); } } diff --git a/router/src/main/java/de/ozgcloud/eingang/router/ConsistingStub.java b/router/src/main/java/de/ozgcloud/eingang/router/ConsistingStub.java index d77a046240e55163800bf7cb512a60dc0e2f6a86..71ee0bb8cd5b3dda20014f97f491aaecb25eff76 100644 --- a/router/src/main/java/de/ozgcloud/eingang/router/ConsistingStub.java +++ b/router/src/main/java/de/ozgcloud/eingang/router/ConsistingStub.java @@ -1,9 +1,10 @@ package de.ozgcloud.eingang.router; +import io.grpc.stub.AbstractStub; import lombok.Builder; @Builder -class ConsistingStub<T> implements ManagableStub<T> { +class ConsistingStub<T extends AbstractStub<?>> implements ManagableStub<T> { private T stub; diff --git a/router/src/main/java/de/ozgcloud/eingang/router/VorgangManagerListProperties.java b/router/src/main/java/de/ozgcloud/eingang/router/VorgangManagerListProperties.java index 93c1fe5c47149ddf62b93b727b5ea62ea1fcb0aa..7d615b5dfe7d4fba58e2bb6c1b1d8d38fe56f2f5 100644 --- a/router/src/main/java/de/ozgcloud/eingang/router/VorgangManagerListProperties.java +++ b/router/src/main/java/de/ozgcloud/eingang/router/VorgangManagerListProperties.java @@ -41,7 +41,6 @@ import jakarta.validation.ConstraintValidatorContext; import jakarta.validation.Payload; import jakarta.validation.constraints.NotNull; -import org.apache.commons.collections.MapUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -141,9 +140,8 @@ class VorgangManagerListProperties { private boolean isZufiConfigured(VorgangManagerListProperties props) { return props.getClientProperties() .map(ps -> ps.getClient()) - .map(client -> MapUtils.getObject(client, Application.ZUFI_MANAGER_GRPC_CLIENT)) - .map(Objects::nonNull) - .orElse(false); + .map(client -> client.get(Application.ZUFI_MANAGER_GRPC_CLIENT)) + .isPresent(); } } } diff --git a/router/src/main/java/de/ozgcloud/eingang/router/VorgangManagerServerResolver.java b/router/src/main/java/de/ozgcloud/eingang/router/VorgangManagerServerResolver.java index 9cffc945d5cf6353bcee7af9f5f0b2adab98b01c..c90fc428df04c7805a5d58a7ad8618a21e67f39e 100644 --- a/router/src/main/java/de/ozgcloud/eingang/router/VorgangManagerServerResolver.java +++ b/router/src/main/java/de/ozgcloud/eingang/router/VorgangManagerServerResolver.java @@ -26,7 +26,6 @@ package de.ozgcloud.eingang.router; import java.util.Collection; import java.util.Collections; import java.util.Optional; -import java.util.function.Function; import jakarta.annotation.PostConstruct; import jakarta.validation.Valid; @@ -40,9 +39,7 @@ import de.ozgcloud.eingang.router.VorgangManagerListProperties.FallbackStrategy; import de.ozgcloud.eingang.router.VorgangManagerListProperties.RoutingStrategy; import de.ozgcloud.eingang.router.errorhandling.AdapterConfigurationException; import de.ozgcloud.eingang.router.errorhandling.UnknownOrganisationseinheitException; -import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc; import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc.BinaryFileServiceStub; -import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc; import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub; import io.grpc.Channel; import io.grpc.ManagedChannel; @@ -71,16 +68,16 @@ public class VorgangManagerServerResolver { @Autowired(required = false) private Collection<StubTransformer> stubTransformers = Collections.emptyList(); - private StubFactory vorgangStubFactory; - private StubFactory binaryFileAsynStubFactory; + private StubFactory vorgangBlockingStubFactory; + private StubFactory binaryFileStubFactory; @Autowired private ZufiService zufiService; @PostConstruct void findApplicableStubFactories() { - vorgangStubFactory = findStubFactory(VorgangServiceBlockingStub.class); - binaryFileAsynStubFactory = findStubFactory(BinaryFileServiceStub.class); + vorgangBlockingStubFactory = findStubFactory(VorgangServiceBlockingStub.class); + binaryFileStubFactory = findStubFactory(BinaryFileServiceStub.class); } StubFactory findStubFactory(Class<? extends AbstractStub<?>> stubClass) { @@ -91,49 +88,51 @@ public class VorgangManagerServerResolver { public ManagableStub<VorgangServiceBlockingStub> resolveVorgangServiceBlockingStubByOrganisationseinheitenId( Optional<String> organisationsEinheitId) { - if (isZufiStrategy()) { - return createStub(organisationsEinheitId, VorgangServiceGrpc::newBlockingStub); - } - return (ManagableStub<VorgangServiceBlockingStub>) createStubByConfiguredChannels(organisationsEinheitId, vorgangStubFactory, - VorgangServiceBlockingStub.class); + return createStub(organisationsEinheitId, vorgangBlockingStubFactory, VorgangServiceBlockingStub.class); } public ManagableStub<BinaryFileServiceStub> resolveBinaryFileServiceStubByOrganisationsEinheitId(Optional<String> organisationsEinheitId) { + return createStub(organisationsEinheitId, binaryFileStubFactory, BinaryFileServiceStub.class); + } + + <T extends AbstractStub<T>> ManagableStub<T> createStub(Optional<String> organisationsEinheitId, StubFactory stubFactory, + Class<? extends AbstractStub<?>> stubClass) { if (isZufiStrategy()) { - return createStub(organisationsEinheitId, BinaryFileServiceGrpc::newStub); + return createCloseableStub(organisationsEinheitId, stubFactory, stubClass); } - return (ManagableStub<BinaryFileServiceStub>) createStubByConfiguredChannels(organisationsEinheitId, binaryFileAsynStubFactory, - BinaryFileServiceStub.class); + return createStubByConfiguredChannels(organisationsEinheitId, stubFactory, stubClass); } private boolean isZufiStrategy() { return properties.getRoutingStrategy() == RoutingStrategy.ZUFI; } - <T> ManagableStub<T> createStub(Optional<String> organisationsEinheitId, Function<ManagedChannel, T> createFunction) { - return ClosableStub.<T>builder() - .channel(createChannel(organisationsEinheitId)) - .createFunction(createFunction) - .build(); + <T extends AbstractStub<T>> ManagableStub<T> createCloseableStub(Optional<String> organisationsEinheitId, StubFactory stubFactory, + Class<? extends AbstractStub<?>> stubClass) { + var channelName = getVorgangManagerAddress(organisationsEinheitId); + var channel = createChannel(channelName); + var stub = stubFactory.createStub(stubClass, channel); + stub = applyStubTransformers(stub, channelName); + return ClosableStub.<T>builder().stub((T) stub).channel(channel).build(); } - ManagedChannel createChannel(Optional<String> organisationsEinheitId) { - return ManagedChannelBuilder.forTarget(getVorgangManagerAddress(organisationsEinheitId)).usePlaintext().build(); + ManagedChannel createChannel(String channelName) { + return ManagedChannelBuilder.forTarget(channelName).usePlaintext().build(); } - private String getVorgangManagerAddress(Optional<String> organisationsEinheitId) { + String getVorgangManagerAddress(Optional<String> organisationsEinheitId) { if (organisationsEinheitId.isEmpty()) { throw new TechnicalException("No organisationsEinheitId exists, can not build connection to vorgang-manager."); } return zufiService.getVorgangManagerUrl(organisationsEinheitId.get()); } - ManagableStub<?> createStubByConfiguredChannels(Optional<String> organisationsEinheitId, StubFactory stubFactory, + <T extends AbstractStub<T>> ManagableStub<T> createStubByConfiguredChannels(Optional<String> organisationsEinheitId, StubFactory stubFactory, Class<? extends AbstractStub<?>> stubClass) { var channelName = getChannelName(organisationsEinheitId); var stub = stubFactory.createStub(stubClass, createChannelByName(channelName)); stub = applyStubTransformers(stub, channelName); - return ConsistingStub.builder().stub(stub).build(); + return ConsistingStub.<T>builder().stub((T) stub).build(); } String getChannelName(Optional<String> organisationsEinheitId) { @@ -141,13 +140,17 @@ public class VorgangManagerServerResolver { } private Optional<String> getChannelTarget(Optional<String> organisationsEinheitId) { - if (properties.getRoutingStrategy() == RoutingStrategy.SINGLE) { + if (isSingleRoutingStrategy()) { return properties.getTargetVorgangManagerName(); } else { return organisationsEinheitId.map(properties.getOrganisationseinheiten()::get); } } + private boolean isSingleRoutingStrategy() { + return properties.getRoutingStrategy() == RoutingStrategy.SINGLE; + } + private String addChannelPrefix(@NonNull String name) { return CHANNEL_NAME_PREFIX + name; } diff --git a/router/src/main/java/de/ozgcloud/eingang/router/VorgangRemoteService.java b/router/src/main/java/de/ozgcloud/eingang/router/VorgangRemoteService.java index b566b57f8894602c379f4e1699bae79e95ca30db..7bf32236907b9e50f81f1138bda9ff1c3c60cf4c 100644 --- a/router/src/main/java/de/ozgcloud/eingang/router/VorgangRemoteService.java +++ b/router/src/main/java/de/ozgcloud/eingang/router/VorgangRemoteService.java @@ -80,8 +80,8 @@ public class VorgangRemoteService { } void logConnection(Optional<String> organisationsEinheitenId, VorgangServiceBlockingStub vorgangStub) { - LOG.info("Connecting to vorgang-manager server " + vorgangStub.getChannel().authority() + "; OrganisationsEinheitId: " - + organisationsEinheitenId); + LOG.info("Connecting to vorgang-manager {0}; OrganisationsEinheitId: {1}.", vorgangStub.getChannel().authority(), + organisationsEinheitenId); } private ManagableStub<VorgangServiceBlockingStub> getVorgangServiceStub(Optional<String> organisationsEinheitenId) { diff --git a/router/src/test/java/de/ozgcloud/eingang/router/VorgangManagerServerResolverTest.java b/router/src/test/java/de/ozgcloud/eingang/router/VorgangManagerServerResolverTest.java index 5bafbdcec6f41c2c094b7803a8317bb85ef9a9b8..08a24dcd900e53769136009f84bc3b3a1bd4a22e 100644 --- a/router/src/test/java/de/ozgcloud/eingang/router/VorgangManagerServerResolverTest.java +++ b/router/src/test/java/de/ozgcloud/eingang/router/VorgangManagerServerResolverTest.java @@ -31,13 +31,11 @@ import static org.mockito.Mockito.*; import java.util.Arrays; import java.util.Collections; import java.util.Optional; -import java.util.function.Function; 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.mockito.ArgumentMatchers; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; @@ -84,7 +82,7 @@ class VorgangManagerServerResolverTest { resolver.findApplicableStubFactories(); - assertThat(ReflectionTestUtils.getField(resolver, "vorgangStubFactory")).isSameAs(stubFactory); + assertThat(ReflectionTestUtils.getField(resolver, "vorgangBlockingStubFactory")).isSameAs(stubFactory); } @Test @@ -108,92 +106,97 @@ class VorgangManagerServerResolverTest { private final Optional<String> organisationsEinheitenId = Optional.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID); - @DisplayName("On zufi strategy") - @Nested - class TestOnZufiRoutingStrategy { + @BeforeEach + void mock() { + ReflectionTestUtils.setField(resolver, "vorgangBlockingStubFactory", stubFactory); - @BeforeEach - void mock() { - doReturn(stub).when(resolver).createStub(any(), any()); - setProperties(VorgangManagerListPropertiesTestFactory.createForZufiRouting()); - } + doReturn(stub).when(resolver).createStub(any(), any(), any()); + } - @Test - void shouldCallCreateStub() { - resolveStub(); + @Test + void shouldCallCreateStub() { + resolveStub(); - verify(resolver).createStub(eq(organisationsEinheitenId), - ArgumentMatchers.<Function<ManagedChannel, VorgangServiceBlockingStub>>any()); - } + verify(resolver).createStub(organisationsEinheitenId, stubFactory, VorgangServiceBlockingStub.class); + } - @Test - void shouldReturnStub() { - var createdStub = resolveStub(); + @Test + void shouldReturnStub() { + var createdStub = resolveStub(); - assertThat(createdStub).isEqualTo(stub); - } + assertThat(createdStub).isEqualTo(stub); } - @DisplayName("On other routing strategy") - @Nested - class TestOnOtherRoutingStrategy { + private ManagableStub<VorgangServiceBlockingStub> resolveStub() { + return resolver.resolveVorgangServiceBlockingStubByOrganisationseinheitenId(organisationsEinheitenId); + } + } - @BeforeEach - void mock() { - doReturn(stub).when(resolver).createStubByConfiguredChannels(any(), any(), any()); - setProperties(VorgangManagerListPropertiesTestFactory.createForSingleRouting()); - } + @DisplayName("Resolve binaryFile service by organisationsEinheitenId") + @Nested + class TestResolveBinaryFileServiceStubByOrganisationsEinheitenId { - @Test - void shouldCallCreateStub() { - resolveStub(); + @Mock + private ManagableStub<BinaryFileServiceStub> stub; - verify(resolver).createStubByConfiguredChannels(eq(organisationsEinheitenId), any(), eq(VorgangServiceBlockingStub.class)); - } + private final Optional<String> organisationsEinheitenId = Optional.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID); - @Test - void shouldReturnStub() { - var createdStub = resolveStub(); + @BeforeEach + void mock() { + ReflectionTestUtils.setField(resolver, "binaryFileStubFactory", stubFactory); - assertThat(createdStub).isEqualTo(stub); - } + doReturn(stub).when(resolver).createStub(any(), any(), any()); } - private ManagableStub<VorgangServiceBlockingStub> resolveStub() { - return resolver.resolveVorgangServiceBlockingStubByOrganisationseinheitenId(organisationsEinheitenId); + @Test + void shouldCallCreateStub() { + resolveStub(); + + verify(resolver).createStub(organisationsEinheitenId, stubFactory, BinaryFileServiceStub.class); + } + + @Test + void shouldReturnStub() { + var createdStub = resolveStub(); + + assertThat(createdStub).isEqualTo(stub); + } + + private ManagableStub<BinaryFileServiceStub> resolveStub() { + return resolver.resolveBinaryFileServiceStubByOrganisationsEinheitId(organisationsEinheitenId); } } - @DisplayName("Resolve binaryFile service by organisationsEinheitenId") + @DisplayName("Create stub") @Nested - class TestResolveBinaryFileServiceStubByOrganisationsEinheitenId { + class TestCreateStub { @Mock - private ManagableStub<BinaryFileServiceStub> stub; + private ManagableStub<?> stub; private final Optional<String> organisationsEinheitenId = Optional.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID); + private final Class<? extends AbstractStub<?>> stubClass = VorgangServiceBlockingStub.class; - @DisplayName("On zufi strategy") + @DisplayName("on zufi strategy") @Nested class TestOnZufiRoutingStrategy { @BeforeEach void mock() { - doReturn(stub).when(resolver).createStub(any(), any()); + doReturn(stub).when(resolver).createCloseableStub(any(), any(), any()); setProperties(VorgangManagerListPropertiesTestFactory.createForZufiRouting()); } @Test void shouldCallCreateStub() { - resolveStub(); + createStub(); - verify(resolver).createStub(eq(organisationsEinheitenId), - ArgumentMatchers.<Function<ManagedChannel, BinaryFileServiceStub>>any()); + verify(resolver).createStub(organisationsEinheitenId, stubFactory, stubClass); } @Test void shouldReturnStub() { - var createdStub = resolveStub(); + var createdStub = createStub(); assertThat(createdStub).isEqualTo(stub); } @@ -211,66 +214,91 @@ class VorgangManagerServerResolverTest { @Test void shouldCallCreateStub() { - resolveStub(); + createStub(); - verify(resolver).createStubByConfiguredChannels(eq(organisationsEinheitenId), any(), eq(BinaryFileServiceStub.class)); + verify(resolver).createStubByConfiguredChannels(organisationsEinheitenId, stubFactory, stubClass); } @Test void shouldReturnStub() { - var createdStub = resolveStub(); + var createdStub = createStub(); assertThat(createdStub).isEqualTo(stub); } } - private ManagableStub<BinaryFileServiceStub> resolveStub() { - return resolver.resolveBinaryFileServiceStubByOrganisationsEinheitId(organisationsEinheitenId); + private <T extends AbstractStub<T>> ManagableStub<T> createStub() { + return resolver.createStub(organisationsEinheitenId, stubFactory, stubClass); } } - @DisplayName("Create stub") + @DisplayName("Create closeable stub") @Nested - class TestCreateStub { + class TestCreateCloseableStub { @Mock - private ManagableStub<?> createdStub; + private ManagableStub<?> manageableStub; @Mock - private Function<ManagedChannel, AbstractStub<?>> createFunction; + private AbstractStub<?> stub; @Mock private ManagedChannel managedChannel; private Optional<String> organisationsEinheitenId = Optional.of(VorgangManagerListPropertiesTestFactory.ORGANISATIONSEINHEIT_ID); + private Class<? extends AbstractStub<?>> stubClass = VorgangServiceBlockingStub.class; + private final String vorgangManagerAddress = "dummyVorgangManagerAddress"; @BeforeEach void mock() { + doReturn(vorgangManagerAddress).when(resolver).getVorgangManagerAddress(any()); doReturn(managedChannel).when(resolver).createChannel(any()); + doReturn(stub).when(resolver).applyStubTransformers(any(), any()); + } + + @Test + void shouldGetVorgangManagerAddress() { + createCloseableStub(); + + verify(resolver).getVorgangManagerAddress(organisationsEinheitenId); } @Test void shouldCreateChannel() { - createStub(); + createCloseableStub(); + + verify(resolver).createChannel(vorgangManagerAddress); + } - verify(resolver).createChannel(organisationsEinheitenId); + @Test + void shouldCreateStub() { + createCloseableStub(); + + verify(stubFactory).createStub(stubClass, managedChannel); + } + + @Test + void shouldApplStubTransformers() { + createCloseableStub(); + + verify(resolver).applyStubTransformers(any(), eq(vorgangManagerAddress)); } @Test void shouldReturnStub() { - var createdStub = (ClosableStub) createStub(); + var createdStub = (ClosableStub) createCloseableStub(); assertThat(createdStub).isNotNull(); + assertThat(createdStub.getStub()).isEqualTo(stub); assertThat(createdStub.getChannel()).isEqualTo(managedChannel); - assertThat(createdStub.getCreateFunction()).isEqualTo(createFunction); } - private ManagableStub<?> createStub() { - return resolver.createStub(organisationsEinheitenId, createFunction); + private <T extends AbstractStub<T>> ManagableStub<T> createCloseableStub() { + return resolver.createCloseableStub(organisationsEinheitenId, stubFactory, stubClass); } } - @DisplayName("Create Channel") + @DisplayName("Get vorgangManager address") @Nested - class TestCreateChannel { + class TestGetVorgangManagerAddress { private final Optional<String> organisationsEinheitenId = Optional.of(VorgangManagerListPropertiesTestFactory.ORGANISATIONSEINHEIT_ID); private final String vorgangManagerAddress = "DummyVorgangManagerAddress"; @@ -279,7 +307,7 @@ class VorgangManagerServerResolverTest { void shouldCallZufiService() { when(zufiService.getVorgangManagerUrl(any())).thenReturn(vorgangManagerAddress); - createChannel(); + getVorgangManagerAddress(); verify(zufiService).getVorgangManagerUrl(VorgangManagerListPropertiesTestFactory.ORGANISATIONSEINHEIT_ID); } @@ -288,20 +316,21 @@ class VorgangManagerServerResolverTest { void shouldThrowExceptionIfOrganisationsEinheitIsNotPresent() { var emptyOrganisationsEinheitId = Optional.<String>empty(); - assertThatThrownBy(() -> resolver.createChannel(emptyOrganisationsEinheitId)).isInstanceOf(TechnicalException.class); + assertThatThrownBy(() -> resolver.getVorgangManagerAddress(emptyOrganisationsEinheitId)).isInstanceOf(TechnicalException.class); } @Test - void shouldReturnChannel() { + void shouldReturnAddress() { when(zufiService.getVorgangManagerUrl(any())).thenReturn(vorgangManagerAddress); - var createdChannel = createChannel(); + var address = getVorgangManagerAddress(); + + assertThat(address).isEqualTo(vorgangManagerAddress); - assertThat(createdChannel).isNotNull(); } - private ManagedChannel createChannel() { - return resolver.createChannel(organisationsEinheitenId); + private String getVorgangManagerAddress() { + return resolver.getVorgangManagerAddress(organisationsEinheitenId); } } @@ -360,26 +389,6 @@ class VorgangManagerServerResolverTest { } } - @DisplayName("Create stub using ZuFi") - @Nested - class TestCreateStubUsingZuFi { - - @Test - void shouldCallOrganisationsEinhetiService() { - - } - - @Test - void shouldCreateStubByGivenUrl() { - - } - - @Test - void shouldReturnCreatedStub() { - - } - } - @Nested class TestGetChannelName { @@ -481,32 +490,6 @@ class VorgangManagerServerResolverTest { } } - @Nested - class TestZufiBasedRouting { - - private Class<? extends AbstractStub<?>> stubClass = VorgangServiceBlockingStub.class; - - @Nested - class CreateStub { - - private VorgangManagerListProperties properties = VorgangManagerListPropertiesTestFactory.createForZufiRouting(); - - @BeforeEach - void setProperties() { - ReflectionTestUtils.setField(resolver, "properties", properties); - } - -// @Test -// void shouldUseZufiToCreateChannel() { -// Optional<String> oeId = Optional.of(VorgangManagerListPropertiesTestFactory.ORGANISATIONSEINHEIT_ID); -// -// resolver.createStub(oeId, stubFactory, stubClass); -// -// verify(resolver).createStubUsingZufi(oeId, stubFactory, stubClass); -// } - } - } - private void setProperties(VorgangManagerListProperties properties) { ReflectionTestUtils.setField(resolver, "properties", properties); }