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.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"));
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
// ensure destination is empty
subscriberClient.getAvailableSubmissionsForDestination(destinationId).forEach(s -> subscriberClient.rejectSubmission(s, List.of()));
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 (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);
ExecutorService es = Executors.newCachedThreadPool();
final SubscriberClient subscriberClient = ClientFactory.createSubscriberClient(config);
for (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(SubscriberClient subscriberClient, SubmissionForPickup submissionForPickup, 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.");
}
}