Newer
Older
package dev.fitko.fitconnect.integrationtests;
import dev.fitko.fitconnect.api.config.ApplicationConfig;
import dev.fitko.fitconnect.api.domain.model.attachment.Attachment;
import dev.fitko.fitconnect.api.domain.model.event.Event;
import dev.fitko.fitconnect.api.domain.model.event.EventState;
import dev.fitko.fitconnect.api.domain.model.event.Status;
import dev.fitko.fitconnect.api.domain.model.event.problems.data.DataEncryptionIssue;
import dev.fitko.fitconnect.api.domain.model.event.problems.data.IncorrectDataAuthenticationTag;
import dev.fitko.fitconnect.api.domain.model.event.problems.other.TechnicalError;
import dev.fitko.fitconnect.api.domain.model.event.problems.submission.InvalidEventLog;
import dev.fitko.fitconnect.api.domain.model.submission.ServiceType;
import dev.fitko.fitconnect.api.domain.model.submission.SubmissionForPickup;
import dev.fitko.fitconnect.api.domain.sender.SendableSubmission;
import dev.fitko.fitconnect.api.domain.subscriber.ReceivedSubmission;
import dev.fitko.fitconnect.api.exceptions.client.FitConnectSubscriberException;
import dev.fitko.fitconnect.api.exceptions.internal.RestApiException;
import dev.fitko.fitconnect.client.SenderClient;
import dev.fitko.fitconnect.client.SubscriberClient;
import dev.fitko.fitconnect.client.bootstrap.ClientFactory;
import dev.fitko.fitconnect.integrationtests.condition.EnableIfEnvironmentVariablesAreSet;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isOneOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@EnableIfEnvironmentVariablesAreSet
public class SubscriberClientIT extends IntegrationTestBase {
cleanupTestSubmissions();
}
void testListSubmissionsForDestination() throws IOException {
final ApplicationConfig config = getConfigWithCredentialsFromEnvironment();
final var senderClient = ClientFactory.createSenderClient(config);
final var subscriberClient = ClientFactory.createSubscriberClient(config);
final UUID destinationId = UUID.fromString(System.getenv("TEST_DESTINATION_ID"));
final String leikaKey = "urn:de:fim:leika:leistung:99400048079000";
final String serviceName = "Test Service";
final String submissionData = getResourceAsString("/submission_data.json");
final URI submissionDataSchemaUri = URI.create("https://schema.fitko.de/fim/s00000114_1.1.schema.json");
final var submissionOne = SendableSubmission.Builder()
.setDestination(destinationId).setServiceType(leikaKey, serviceName)
.setJsonData(submissionData, submissionDataSchemaUri)
.build();
final var submissionTwo = SendableSubmission.Builder()
.setDestination(destinationId).setServiceType(leikaKey, serviceName)
.setJsonData(submissionData, submissionDataSchemaUri)
.build();
final var sentSubmissionOne = senderClient.send(submissionOne);
final var sentSubmissionTwo = senderClient.send(submissionTwo);
assertNotNull(sentSubmissionOne);
assertNotNull(sentSubmissionTwo);
// When
final Set<SubmissionForPickup> submissions = subscriberClient.getAvailableSubmissionsForDestination(destinationId);
// Then
Assertions.assertFalse(submissions.isEmpty());
final List<UUID> submissionIds = submissions.stream().map(SubmissionForPickup::getSubmissionId).collect(Collectors.toList());
assertThat(submissionIds, Matchers.hasItems(sentSubmissionOne.getSubmissionId(), sentSubmissionTwo.getSubmissionId()));
void testReceiveSingleSubmission() throws IOException {
final ApplicationConfig config = getConfigWithCredentialsFromEnvironment();
final var senderClient = ClientFactory.createSenderClient(config);
final var subscriberClient = ClientFactory.createSubscriberClient(config);
final UUID destinationId = UUID.fromString(System.getenv("TEST_DESTINATION_ID"));
final String leikaKey = "urn:de:fim:leika:leistung:99400048079000";
final String serviceName = "Test Service";
final String submissionData = getResourceAsString("/submission_data.json");
final var submission = SendableSubmission.Builder()
.setDestination(destinationId).setServiceType(leikaKey, serviceName)
.setJsonData(submissionData, URI.create("https://schema.fitko.de/fim/s00000114_1.1.schema.json"))
.addAttachment(Attachment.fromByteArray("foo".getBytes(), "plain/text"))
.build();
final var sentSubmission = senderClient.send(submission);
assertNotNull(sentSubmission);
// When
final ReceivedSubmission receivedSubmission = subscriberClient.requestSubmission(sentSubmission.getSubmissionId());
// Then
assertNotNull(receivedSubmission);
assertThat(receivedSubmission.getAttachments(), hasSize(1));
assertThat(receivedSubmission.getAttachments().get(0).getDataAsString(StandardCharsets.UTF_8), is("foo"));
assertThat(receivedSubmission.getDataAsString(), is(submissionData));
assertThat(receivedSubmission.getServiceType(), is(new ServiceType(serviceName, leikaKey)));
@Test
void testReceiveSubmissionWithUrnSchemaValidation(@TempDir final Path tempDir) throws IOException {
// Given
// Prepare locally set submission data schema for a urn schema in given path
final String schemaResource = getResourceAsString("/submission-data-schema/submission_data_schema.json");
final Path schemaPath = Files.writeString(Path.of(tempDir.toString(), "submission_data_schema.json"), schemaResource);
final String schemaUri = "urn:de:fitko:test:schema";
final ApplicationConfig config = getConfigWithCredentialsFromEnvironment(true, Map.of(schemaUri, schemaPath.toString()));
final String submissionData = getResourceAsString("/submission_data.json");
final var submission = SendableSubmission.Builder()
.setDestination(UUID.fromString(System.getenv("TEST_DESTINATION_ID")))
.setServiceType("urn:de:fim:leika:leistung:99400048079001", "Test Service")
.setJsonData(submissionData, URI.create("urn:de:fitko:test:schema"))
.build();
// When
final var sentSubmission = ClientFactory.createSenderClient(config).send(submission);
// Then
assertNotNull(sentSubmission);
// When
final ReceivedSubmission receivedSubmission = ClientFactory.createSubscriberClient(config).requestSubmission(sentSubmission.getSubmissionId());
// Then
assertNotNull(receivedSubmission);
}
@Test
void testRejectEvent() throws IOException {
// Given
final ApplicationConfig config = getConfigWithCredentialsFromEnvironment();
final String submissionData = getResourceAsString("/submission_data.json");
final SenderClient senderClient = ClientFactory.createSenderClient(config);
final var submission = SendableSubmission.Builder()
.setDestination(UUID.fromString(System.getenv("TEST_DESTINATION_ID")))
.setServiceType("urn:de:fim:leika:leistung:99400048079000", "Test Service")
.setJsonData(submissionData, URI.create("https://schema.fitko.de/fim/s00000114_1.1.schema.json"))
.addAttachment(Attachment.fromPath(Path.of("src/test/resources/attachment.txt"), "plain/text"))
.build();
final var sentSubmission = senderClient.send(submission);
assertNotNull(sentSubmission);
// When
final var subscriberClient = ClientFactory.createSubscriberClient(config);
final var sentSubmissionId = sentSubmission.getSubmissionId();
// reject and remove
subscriberClient.requestSubmission(sentSubmissionId).rejectSubmission(List.of(new DataEncryptionIssue()));
// check event log if reject event was sent
final Status status = senderClient.getSubmissionStatus(sentSubmission);
assertThat(status.getState(), is(EventState.REJECTED));
// second attempt to receive and reject the submission should return an empty result
// since the submission is gone after being rejected
final FitConnectSubscriberException exception = assertThrows(FitConnectSubscriberException.class, () -> subscriberClient.requestSubmission(sentSubmissionId));
assertThat(exception.getCause(), instanceOf(RestApiException.class));
assertThat(((RestApiException) exception.getCause()).getStatusCode(), is(404));
}
@Test
void testAcceptEvent() throws IOException {
// Given
final ApplicationConfig config = getConfigWithCredentialsFromEnvironment();
final String submissionData = getResourceAsString("/submission_data.json");
final SenderClient senderClient = ClientFactory.createSenderClient(config);
final SubscriberClient subscriberClient = ClientFactory.createSubscriberClient(config);
final var submission = SendableSubmission.Builder()
.setDestination(UUID.fromString(System.getenv("TEST_DESTINATION_ID")))
.setServiceType("urn:de:fim:leika:leistung:99400048079000", "Test Service")
.setJsonData(submissionData, URI.create("https://schema.fitko.de/fim/s00000114_1.1.schema.json"))
.addAttachment(Attachment.fromPath(Path.of("src/test/resources/attachment.txt"), "plain/text"))
.build();
final var sentSubmission = senderClient.send(submission);
Assertions.assertNotNull(sentSubmission);
// When
final var sentSubmissionId = sentSubmission.getSubmissionId();
// accept and remove
subscriberClient.requestSubmission(sentSubmissionId).acceptSubmission();
// check event log if accept event was sent
final Status status = senderClient.getSubmissionStatus(sentSubmission);
assertThat(status.getState(), is(EventState.ACCEPTED));
// second attempt to receive the submission should return an empty result
// since the submission is gone after being accepted
final FitConnectSubscriberException exception = assertThrows(FitConnectSubscriberException.class, () -> subscriberClient.requestSubmission(sentSubmissionId));
assertThat(exception.getCause(), instanceOf(RestApiException.class));
assertThat(((RestApiException) exception.getCause()).getStatusCode(), is(404));
}
@Test
void testAcceptEventWithProblem() throws IOException {
// Given
final ApplicationConfig config = getConfigWithCredentialsFromEnvironment();
final String submissionData = getResourceAsString("/submission_data.json");
final var submission = SendableSubmission.Builder()
.setDestination(UUID.fromString(System.getenv("TEST_DESTINATION_ID")))
.setServiceType("urn:de:fim:leika:leistung:99400048079000", "Test Service")
.setJsonData(submissionData, URI.create("https://schema.fitko.de/fim/s00000114_1.1.schema.json"))
.addAttachment(Attachment.fromPath(Path.of("src/test/resources/attachment.txt"), "plain/text"))
.build();
final SenderClient senderClient = ClientFactory.createSenderClient(config);
final var subscriberClient = ClientFactory.createSubscriberClient(config);
final var sentSubmission = senderClient.send(submission);
assertNotNull(sentSubmission);
// When
final var sentSubmissionId = sentSubmission.getSubmissionId();
// accept and remove
subscriberClient.requestSubmission(sentSubmissionId).acceptSubmission(new IncorrectDataAuthenticationTag());
// check event log if accept event was sent and contains a problem
// check event log if accept event was sent
final Status status = senderClient.getSubmissionStatus(sentSubmission);
assertThat(status.getState(), is(EventState.ACCEPTED));
// second attempt to receive the submission should return an empty result
// since the submission is gone after being accepted
final FitConnectSubscriberException exception = assertThrows(FitConnectSubscriberException.class, () -> subscriberClient.requestSubmission(sentSubmissionId));
assertThat(exception.getCause(), instanceOf(RestApiException.class));
assertThat(((RestApiException) exception.getCause()).getStatusCode(), is(404));
}
@Test
void testRejectEventViaClient() throws IOException {
// Given
final ApplicationConfig config = getConfigWithCredentialsFromEnvironment();
final String submissionData = getResourceAsString("/submission_data.json");
final SenderClient senderClient = ClientFactory.createSenderClient(config);
final SubscriberClient subscriberClient = ClientFactory.createSubscriberClient(config);
final var submission = SendableSubmission.Builder()
.setDestination(UUID.fromString(System.getenv("TEST_DESTINATION_ID")))
.setServiceType("urn:de:fim:leika:leistung:99400048079000", "Test Service")
.setJsonData(submissionData, URI.create("https://schema.fitko.de/fim/s00000114_1.1.schema.json"))
.addAttachment(Attachment.fromPath(Path.of("src/test/resources/attachment.txt"), "text/plain"))
.build();
final var sentSubmission = senderClient.send(submission);
assertNotNull(sentSubmission);
// When
final Optional<SubmissionForPickup> submissionForPickup = subscriberClient.getAvailableSubmissionsForDestination(submission.getDestinationId())
.stream()
.filter(s -> s.getSubmissionId().equals(sentSubmission.getSubmissionId()))
.findFirst();
assertTrue(submissionForPickup.isPresent());
subscriberClient.rejectSubmission(submissionForPickup.get(), List.of(new InvalidEventLog()));
// Then
assertThat(senderClient.getSubmissionStatus(sentSubmission).getState(), is(EventState.REJECTED));
// second attempt to receive and reject the submission should return an empty result since the submission is gone after being rejected
final FitConnectSubscriberException exception = assertThrows(FitConnectSubscriberException.class, () -> subscriberClient.requestSubmission(sentSubmission.getSubmissionId()));
assertThat(exception.getCause(), instanceOf(RestApiException.class));
assertThat(((RestApiException) exception.getCause()).getStatusCode(), is(404));
}
@Test
void testReadSubmissionStatus() throws IOException {
// Given
final ApplicationConfig config = getConfigWithCredentialsFromEnvironment();
final String submissionData = getResourceAsString("/submission_data.json");
final SenderClient senderClient = ClientFactory.createSenderClient(config);
final SubscriberClient subscriberClient = ClientFactory.createSubscriberClient(config);
final var submission = SendableSubmission.Builder()
.setDestination(UUID.fromString(System.getenv("TEST_DESTINATION_ID")))
.setServiceType("urn:de:fim:leika:leistung:99400048079000", "Test Service")
.setJsonData(submissionData, URI.create("https://schema.fitko.de/fim/s00000114_1.1.schema.json"))
.addAttachment(Attachment.fromPath(Path.of("src/test/resources/attachment.txt"), "plain/text"))
.build();
final var sentSubmission = senderClient.send(submission);
Assertions.assertNotNull(sentSubmission);
final Status statusForSubmission = subscriberClient.getSubmissionStatus(sentSubmission.getDestinationId(), sentSubmission.getCaseId(), sentSubmission.getSubmissionId());
assertThat(statusForSubmission.getState(), isOneOf(Event.SUBMIT_SUBMISSION.getState(), Event.NOTIFY_SUBMISSION.getState()));
}
@Test
void testReadAllSubmissionsOrderedByIssuedAtTimestamp() throws IOException {
// Given
final ApplicationConfig config = getConfigWithCredentialsFromEnvironment();
final SenderClient senderClient = ClientFactory.createSenderClient(config);
final SubscriberClient subscriberClient = ClientFactory.createSubscriberClient(config);
final String submissionData = getResourceAsString("/submission_data.json");
final UUID destinationId = UUID.fromString(System.getenv("TEST_DESTINATION_ID"));
// ensure destination is empty
subscriberClient.getAvailableSubmissionsForDestination(destinationId).forEach(s -> subscriberClient.rejectSubmission(s, List.of(new TechnicalError())));
assertThat(subscriberClient.getAvailableSubmissionsForDestination(destinationId), hasSize(0));
final var submission = SendableSubmission.Builder()
.setDestination(destinationId)
.setServiceType("urn:de:fim:leika:leistung:99400048079000", "Test Service")
.setJsonData(submissionData, URI.create("https://schema.fitko.de/fim/s00000114_1.1.schema.json"))
.build();
IntStream.range(0, 5).forEach(index -> {
try {
senderClient.send(submission);
// create some distance between submission dates
Thread.sleep(1000);
} catch (final InterruptedException e) {
throw new RuntimeException(e);
}
});
final List<Date> submissionDates = subscriberClient.getAvailableSubmissionsForDestination(destinationId).stream()
.map(subscriberClient::requestSubmission)
// receivedSubmission implements comparable on issuedAt
.sorted()
.map(ReceivedSubmission::getSubmittedAt)
.collect(Collectors.toList());
assertThat(submissionDates, hasSize(5));
boolean consecutiveSubmissionDates = false;
for (int i = 0; i < submissionDates.size() - 1; i++) {
consecutiveSubmissionDates = submissionDates.get(i + 1).toInstant().isAfter(submissionDates.get(i).toInstant());
}
assertTrue(consecutiveSubmissionDates);
@Test
void testMultiThreadExecution() throws IOException, InterruptedException {
// Given
final ApplicationConfig config = getConfigWithCredentialsFromEnvironment();
final String submissionData = getResourceAsString("/submission_data.json");
final SenderClient senderClient = ClientFactory.createSenderClient(config);
final var submission = SendableSubmission.Builder()
.setDestination(UUID.fromString(System.getenv("TEST_DESTINATION_ID")))
.setServiceType("urn:de:fim:leika:leistung:99400048079000", "Test Service")
.setJsonData(submissionData, URI.create("https://schema.fitko.de/fim/s00000114_1.1.schema.json"))
.addAttachment(Attachment.fromPath(Path.of("src/test/resources/attachment.txt"), "plain/text"))
.build();
IntStream.range(0, 10).mapToObj(i -> submission).forEach(senderClient::send);
final ExecutorService es = Executors.newCachedThreadPool();
final SubscriberClient subscriberClient = ClientFactory.createSubscriberClient(config);
for (final SubmissionForPickup submissionForPickup : subscriberClient.getAvailableSubmissionsForDestination(submission.getDestinationId())) {
es.execute(new SubscriberRunner(subscriberClient, submissionForPickup, "Thread-" + submissionForPickup.getSubmissionId()));
}
es.shutdown();
es.awaitTermination(1, TimeUnit.MINUTES);
static class SubscriberRunner implements Runnable {
private final SubscriberClient subscriberClient;
private final SubmissionForPickup submissionForPickup;
private final String threadName;
SubscriberRunner(final SubscriberClient subscriberClient, final SubmissionForPickup submissionForPickup, final String threadName) {
this.subscriberClient = subscriberClient;
this.submissionForPickup = submissionForPickup;
this.threadName = threadName;
System.out.println("Creating " + threadName);
}
public void run() {
System.out.println("Running " + threadName);
assertNotNull(subscriberClient.requestSubmission(submissionForPickup));
System.out.println("Thread " + threadName + " exiting.");
}
}