-
Martin Vogel authoredMartin Vogel authored
- About the FIT-Connect Java SDK
- Outline
- Getting Started
- Build Dependencies
- Prerequisites
- Add FIT-Connect SDK to your build
- Modules
- Setup
- API Usage for Sender
- Hand in already encrypted submission (e.g. from frontend)
- 1. Retrieve public encryption key:
- 2. Send encrypted data
- Hand in a new submission with unencrypted data
- Read the Event-Log
- Read the latest status of a submission
- API Usage for Subscriber
- Retrieving submissions
- List with pagination
- List without pagination
- Receive single submission
- Sending events to the event-log
- Accepting a submission
- Rejecting a submission
- Read the Event-Log
- Roadmap
- Contact
- License
\textcolor{#890000}{\text{THIS SDK IS IN DEVELOPMENT AND NOT READY FOR PRODUCTION USE YET!!!}}
About the FIT-Connect Java SDK
The Java SDK for FIT-Connect enables to build clients for senders and subscribers without directly interacting with any REST-Endpoints. It provides a simple fluent API that guides through the creation and sending of a submission, as well as receiving submissions as a subscriber.
For further information, check out the official docs: FIT-Connect Documentation as well as the:
Outline
- About the FIT-Connect Java SDK
- Outline
- Getting Started
- Modules
- Setup
- API Usage for Sender
- API Usage for Subscriber
- Roadmap
- Contact
- License
Getting Started
How to set up the SDK project locally.
Build Dependencies
This section lists major frameworks/libraries used in the SDK.
- Java 11 (LTS)
- Maven 3.x
- Junit 5
FIT-Connect dependencies:
Further 3rd party dependencies:
- Nimbus-Jose JWT
- Spring Web/HTTP
- Jackson FasterXMl
- JCommander
- Snakeyaml
- OpenCSV
Prerequisites
- Java Runtime >= 11, check your current setup in your commandline
java --version
Add FIT-Connect SDK to your build
To add a dependency on FIT-Connect using Maven, use the following:
<dependency>
<groupId>dev.fitko.fitconnect.sdk</groupId>
<artifactId>client</artifactId>
<version>[Latest Version]</version>
</dependency>
With [Latest Version]
of the last stable build or snapshot.
If you use a snapshot version, please add the maven snapshot repo to your pom.
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
Modules
See the projects' module documentation for more specific information:
Setup
The following steps show how to get the SDK running
-
Create and account on the self-service portal
-
Get your sender/subscriber API-key credentials
-
Clone the sdk repo
git clone https://git.fitko.de/fit-connect/sdk-java
-
Build the project with the included maven wrapper (no separate maven installation needed)
./mvnw clean install -DskipTests
-
Configure your
config.yml
- add Sender OAuth credentials from the self-service portal to SENDER section
- add Subscriber OAuth credentials from the self-service portal to SUBSCRIBER section
- add reference to private decryption key (JWK) to SUBSCRIBER section
- add reference to private signature key (JWK) to SUBSCRIBER section
-
Provide config via environment variable
FIT_CONNECT_CONFIG
or load the config withfinal var config = ApplicationConfigLoader.loadConfig("absolute/path/to/config.yml"); final var senderClient = ClientFactory.senderClient(config);
API Usage for Sender
For sending submission and already encrypted submissions builder are provided to construct the necessary payload to be sent. Builders allow method chaining and guide through all necessary steps.
The examples below expect a loaded configuration via the ApplicationConfigLoader.
Hand in already encrypted submission (e.g. from frontend)
If all data, metadata and attachments are encrypted outside the SDK the sender client allows to retrieve the public key for encryption as well as sending of already encrypted payloads.
For further information on how to implement end-2-end encryption please check the FIT-Connect documentation.
1. Retrieve public encryption key:
final var destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final Optional<String> publicJwk = ClientFactory.senderClient(config).getPublicKey(destinationId);
2. Send encrypted data
To send an encrypted submission the builder EncryptedSubmissionBuilder
is needed to construct an EncryptedSubmissionPayload
object.
The payload can be submitted as shown below via the ClientFactory
.
If optional attachments are added, the UUID needs to be provided for each attachment to be able to announce them before the submission is actually sent. This is necessary because the SDK does not have access to the already encrypted metadata that, which contains that information.
// The constructed client can be reused to send multiple submissions
final SenderClient senderClient = ClientFactory.senderClient(config);
final EncryptedSubmissionPayload frontendEncryptedPayload = EncryptedSubmissionBuilder.Builder()
.withEncryptedAttachment(UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"), "$encrpyt€ed @tt@chment") // optional
.withEncryptedData("{$encrpyt€ed json}")
.withEncryptedMetadata("$encrpyt€ed metadata")
.withDestination(UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"))
.withServiceType("Führerscheinummeldung", "urn:de:fim:leika:leistung:99400048079000")
.build();
final SentSubmission sentSubmission = senderClient.submit(frontendEncryptedPayload);
Hand in a new submission with unencrypted data
If all data, metadata and attachments are encrypted in the sender using the SDK, the client automatically handles the encryption.
Be aware that this example is not end-2-end encrypted, see FIT-Connect documentation for details.
To send a submission the builder SubmissionBuilder
is needed to construct a SubmissionPayload
object.
The payload can be submitted as shown below via the ClientFactory
.
// The constructed client can be reused to send multiple submissions
final SenderClient senderClient = ClientFactory.senderClient(config);
final SubmissionPayload submissionPayload = SubmissionBuilder.Builder()
.withAttachment(Path.of("path/to/attachment.txt").toFile()) // optional
.withJsonData("{ \"foo\" : \"bar\"}")
.withDestination(UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"))
.withServiceType("Führerscheinummeldung", "urn:de:fim:leika:leistung:99400048079000")
.build();
final SentSubmission sentSubmission = senderClient.submit(submissionPayload);
Read the Event-Log
To read the event-log, destinationId and caseId are needed.
final var caseId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final var destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final List<EventLogEntry> eventLog = ClientFactory.senderClient(config).getEventLog(caseId, destinationId);
for(EventLogEntry logEntry: eventLog) {
LOGGER.info("Event: {}", logEntry.getEvent());
LOGGER.info("EventId: {}", logEntry.getEventId());
LOGGER.info("Issued at: {}", logEntry.getIssueTime());
LOGGER.info("Issuer: {}", logEntry.getIssuer());
LOGGER.info("CaseId: {}", logEntry.getCaseId());
LOGGER.info("SubmissionId: {}", logEntry.getSubmissionId());
LOGGER.info("Problems: {}", logEntry.getProblems());
}
The log contains the event, issuer and occurred problems like shown in the example output below:
Event: https://schema.fitko.de/fit-connect/events/submit-submission
EventId: 659bcbe7-fd53-4313-a1c3-192bccc95f94
Issued at: Thu Dec 15 10:23:51 CET 2022
Issuer: https://submission-api-testing.fit-connect.fitko.dev
CaseId: cb9a5a78-0ec6-492c-b652-0d7aa5e488b0
SubmissionId: 7502200b-f12d-4fc5-9669-ad3e3337396b
Problems: []
Read the latest status of a submission
Instead of the entire log, the latest status for a submission can be retrieved as well.
final SentSubmission sentSubmission = ... // persisted sent submission by sender client
final EventStatus eventStatus = ClientFactory.senderClient(config).getStatusForSubmission(sentSubmission);
LOGGER.info("Current status for submission {} => {}", sentSubmission.getSubmissionId(), eventStatus.getStatus());
The example output shows the current state of the submission after being created, following the transitions in the diagram below:
Current status for submission 43cf7163-5163-4bc8-865e-be96e271ecc3 => incomplete
API Usage for Subscriber
Retrieving submissions
Submissions can be fetched by id or as a list of submissions for a specific case.
List with pagination
Limit and offset parameters allow to page through the result.
final int offset = 0;
final int limit = 100;
final var destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final Set<SubmissionForPickup> firstOneHundredSubmissions = ClientFactory.subscriberClient(config).getAvailableSubmissions(destinationId), limit, offset);
List without pagination
Listing available submissions without pagination pulls the first 500 entries.
final var destinationId= UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final Set<SubmissionForPickup> submissions = ClientFactory.subscriberClient(config).getAvailableSubmissions(destinationId);
Receive single submission
final submissionId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final ReceivedSubmission receivedSubmission = ClientFactory.subscriberClient(config).requestSubmission(submissionId);
Now, the received submission allows access to the decrypted data, attachments, metadata and ids
// access data
final String data = receivedData.getData();
final URI dataSchemaUri = receivedData.getDataSchemaUri();
final MimeType mimeType = receivedData.getDataMimeType();
// access metadata
final Metadata = receivedData.getSubmissionMetdata();
// access attachments
for(final ReceivedAttachment attachment : receivedSubmission.getAttachments()){
final byte[] attachmentRawData = attachment.getData();
final String originalFilename = attachment.getFilename();
final UUID attachmentId = attachment.getAttachmentId();
}
// access further ids of submission
final UUID caseId = receivedData.getCaseId();
final UUID submissionId = receivedData.getSubmissionId();
final UUID destinationId = receivedData.getDestinationId();
Sending events to the event-log
In order to accept or reject a submission, the subscriber client can send events (security-event-tokens) to the event-log. For more details please see the documentation on events and the creation of set-events.
Accepting a submission
If the functional review by the subscriber was positive, the submission can be accepted with an accept-submission
event.
final var submissionId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
ClientFactory.subscriberClient(config)
.requestSubmission(submissionId)
.acceptSubmission();
After the accept event was sent the submission transitions into the state deleted
and is removed.
Rejecting a submission
If the functional or technical review by the subscriber was negative, e.g. there is a discrepancy within the semantics of the data, the submission can be rejected with an reject-submission
event.
The rejection takes a list of dev.fitko.fitconnect.api.domain.model.event.problems.*
as parameter to specify the problem.
See the Fit-Connect documentation for more details on available (technical) problems.
final var submissionId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final var rejectionProblems = List.of(new DataSchemaViolation());
ClientFactory.subscriberClient(config)
.requestSubmission(submissionId)
.rejectSubmission(rejectionProblems);
After the rejection event was sent the submission transitions into the state deleted
and is removed.
Read the Event-Log
To read the event-log, destinationId and caseId are needed.
final var caseId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final var destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final List<EventLogEntry> eventLog = ClientFactory.subscriberClient(config).getEventLog(caseId, destinationId);
for(EventLogEntry logEntry: eventLog) {
LOGGER.info("Event: {}", logEntry.getEvent());
LOGGER.info("EventId: {}", logEntry.getEventId());
LOGGER.info("Issued at: {}", logEntry.getIssueTime());
LOGGER.info("Issuer: {}", logEntry.getIssuer());
LOGGER.info("CaseId: {}", logEntry.getCaseId());
LOGGER.info("SubmissionId: {}", logEntry.getSubmissionId());
LOGGER.info("Problems: {}", logEntry.getProblems());
}
The log contains the event, issuer and occurred problems like shown in the example output below:
Event: https://schema.fitko.de/fit-connect/events/create-submission
EventId: 659bcbe7-fd53-4313-a1c3-192bccc95f94
Issued at: Thu Dec 15 10:23:51 CET 2022
Issuer: https://submission-api-testing.fit-connect.fitko.dev
CaseId: cb9a5a78-0ec6-492c-b652-0d7aa5e488b0
SubmissionId: 7502200b-f12d-4fc5-9669-ad3e3337396b
Problems: []
For more details please see the event-log documentation.
Roadmap
- Add Routing features
- Add Callback validation
- Add auto-reject on technical errors
- Maven central release of 1.0.0
See the open issues for a full list of proposed features (and known issues).
Contact
FIT-Connect Contact Page for further information
License
Source code is licensed under the EUPL.
Rechtlicher Hinweis: Dieses Software Development Kit (SDK) ist dazu bestimmt, die Anbindung einer Software an die FIT-Connect-Infrastruktur zu ermöglichen. Hierfür kann das SDK in die anzubindenden Software integriert werden. Erfolgt die Integration des SDK in unveränderter Form, liegt keine Bearbeitung im Sinne der EUPL bzw. des deutschen Urheberrechts vor. Die Art und Weise der Verlinkung des SDK führt insbesondere nicht zur Schaffung eines abgeleiteten Werkes. Die unveränderte Übernahme des SDK in eine anzubindende Software führt damit nicht dazu, dass die anzubindende Software unter den Bedingungen der EUPL zu lizenzieren ist. Für die Weitergabe des SDK selbst - in unveränderter oder bearbeiteter Form, als Quellcode oder ausführbares Programm - gelten die Lizenzbedingungen der EUPL in unveränderter Weise.