Skip to content
Snippets Groups Projects
Commit 02716fe8 authored by Martin Vogel's avatar Martin Vogel
Browse files

#414 Use WebClient to enable future async http calls

parent bbba7c7a
No related branches found
No related tags found
2 merge requests!2#414 Remaining changes from MR,!1planning#414 Methoden Signaturen (Zwischenstand)
/**
* This module is providing the internal sdk api
* <p>
*
* </p>
*
* @since 1.0
* @author FitConnect
* @version 1.0
*/
package fitconnect.api;
\ No newline at end of file
...@@ -8,7 +8,7 @@ import fitconnect.api.services.validation.CertificateValidator; ...@@ -8,7 +8,7 @@ import fitconnect.api.services.validation.CertificateValidator;
import fitconnect.api.services.validation.MetadataValidator; import fitconnect.api.services.validation.MetadataValidator;
import fitconnect.impl.SubmissionSender; import fitconnect.impl.SubmissionSender;
import fitconnect.impl.SubmissionSubscriber; import fitconnect.impl.SubmissionSubscriber;
import fitconnect.impl.auth.FitCoAuthService; import fitconnect.impl.auth.MonoPublisherOAuthService;
import fitconnect.impl.crypto.JWECryptoService; import fitconnect.impl.crypto.JWECryptoService;
import fitconnect.impl.validation.KeyValidator; import fitconnect.impl.validation.KeyValidator;
import fitconnect.impl.validation.MetadataSubmissionValidator; import fitconnect.impl.validation.MetadataSubmissionValidator;
...@@ -38,7 +38,7 @@ public class ClientFactory { ...@@ -38,7 +38,7 @@ public class ClientFactory {
return new JWECryptoService(); return new JWECryptoService();
} }
private static FitCoAuthService getAuthService() { private static MonoPublisherOAuthService getAuthService() {
return new FitCoAuthService(HttpClient.newHttpClient(), TOKEN_URL); return new MonoPublisherOAuthService(TOKEN_URL);
} }
} }
...@@ -13,30 +13,30 @@ import java.util.Optional; ...@@ -13,30 +13,30 @@ import java.util.Optional;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
public class FitConnectClient { public class SenderClient {
private static final Logger logger = SdkLogger.customLogger(FitConnectClient.class); private static final Logger logger = SdkLogger.customLogger(SenderClient.class);
private final Sender sender; private final Sender sender;
private Optional<OAuthToken> token = Optional.empty(); private Optional<OAuthToken> token = Optional.empty();
public FitConnectClient(){ public SenderClient(){
this.sender = ClientFactory.submissionSender(); this.sender = ClientFactory.submissionSender();
} }
public FitConnectClient authenticate(String clientId, String secret, String...scope){ public SenderClient authenticate(String clientId, String secret, String...scope){
this.token = sender.retrieveOAuthToken(clientId,secret,scope); this.token = sender.retrieveOAuthToken(clientId,secret,scope);
return this; return this;
} }
public FitConnectClient createSubmission(final Submission submission){ public SenderClient createSubmission(final Submission submission){
checkIfAuthenticated(); checkIfAuthenticated();
// TODO implement sendSubmission // TODO implement sendSubmission
logger.log(Level.INFO, "created new submission"); logger.log(Level.INFO, "created new submission");
return this; return this;
} }
public FitConnectClient sendSubmission(final Metadata metadata, final Data data){ public SenderClient sendSubmission(final Metadata metadata, final Data data){
checkIfAuthenticated(); checkIfAuthenticated();
// TODO implement // TODO implement
logger.log(Level.INFO, "successfully sent submission"); logger.log(Level.INFO, "successfully sent submission");
...@@ -44,14 +44,14 @@ public class FitConnectClient { ...@@ -44,14 +44,14 @@ public class FitConnectClient {
return this; return this;
} }
public FitConnectClient uploadAttachments(final List<Attachment> attachments){ public SenderClient uploadAttachments(final List<Attachment> attachments){
checkIfAuthenticated(); checkIfAuthenticated();
// TODO implement // TODO implement
logger.log(Level.INFO, "uploaded " + attachments.size() + " attachments"); logger.log(Level.INFO, "uploaded " + attachments.size() + " attachments");
return this; return this;
} }
public FitConnectClient printToken(){ public SenderClient printToken(){
checkIfAuthenticated(); checkIfAuthenticated();
logger.log(Level.INFO, "retrieved access token: " + this.token.get().getAccessToken()); logger.log(Level.INFO, "retrieved access token: " + this.token.get().getAccessToken());
return this; return this;
...@@ -59,7 +59,7 @@ public class FitConnectClient { ...@@ -59,7 +59,7 @@ public class FitConnectClient {
private void checkIfAuthenticated() { private void checkIfAuthenticated() {
if(token.isEmpty()){ if(token.isEmpty()){
throw new IllegalStateException("not authenticated, please authenticate first with authenticate(client, secret)"); throw new IllegalStateException("not authenticated, please authenticate first");
} }
} }
......
...@@ -13,7 +13,7 @@ public class TestRunner { ...@@ -13,7 +13,7 @@ public class TestRunner {
var clientId = "781f6213-0f0f-4a79-9372-e7187ffda98b"; var clientId = "781f6213-0f0f-4a79-9372-e7187ffda98b";
var secret = "PnzR8Vbmhpv_VwTkT34wponqXWK8WBm-LADlryYdV4o"; var secret = "PnzR8Vbmhpv_VwTkT34wponqXWK8WBm-LADlryYdV4o";
FitConnectClient client = new FitConnectClient(); SenderClient client = new SenderClient();
// sample high -level- api calls to send a submission // sample high -level- api calls to send a submission
client.authenticate(clientId,secret) client.authenticate(clientId,secret)
......
...@@ -32,6 +32,10 @@ ...@@ -32,6 +32,10 @@
<groupId>com.github.erosb</groupId> <groupId>com.github.erosb</groupId>
<artifactId>everit-json-schema</artifactId> <artifactId>everit-json-schema</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies> </dependencies>
......
...@@ -13,7 +13,7 @@ import fitconnect.api.exceptions.EncryptionException; ...@@ -13,7 +13,7 @@ import fitconnect.api.exceptions.EncryptionException;
import fitconnect.impl.logger.SdkLogger; import fitconnect.impl.logger.SdkLogger;
import fitconnect.api.services.validation.CertificateValidator; import fitconnect.api.services.validation.CertificateValidator;
import fitconnect.api.domain.validation.ValidationResult; import fitconnect.api.domain.validation.ValidationResult;
import fitconnect.impl.auth.FitCoAuthService; import fitconnect.impl.auth.MonoPublisherOAuthService;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
...@@ -24,7 +24,7 @@ import java.util.logging.Logger; ...@@ -24,7 +24,7 @@ import java.util.logging.Logger;
public class SubmissionSender implements Sender { public class SubmissionSender implements Sender {
private static final Logger logger = SdkLogger.defaultLogger(FitCoAuthService.class); private static final Logger logger = SdkLogger.defaultLogger(MonoPublisherOAuthService.class);
private final OAuthService authService; private final OAuthService authService;
private final CertificateValidator certificateValidator; private final CertificateValidator certificateValidator;
......
...@@ -13,7 +13,7 @@ import fitconnect.api.exceptions.DecryptionException; ...@@ -13,7 +13,7 @@ import fitconnect.api.exceptions.DecryptionException;
import fitconnect.impl.logger.SdkLogger; import fitconnect.impl.logger.SdkLogger;
import fitconnect.api.services.validation.MetadataValidator; import fitconnect.api.services.validation.MetadataValidator;
import fitconnect.api.domain.validation.ValidationResult; import fitconnect.api.domain.validation.ValidationResult;
import fitconnect.impl.auth.FitCoAuthService; import fitconnect.impl.auth.MonoPublisherOAuthService;
import java.util.Optional; import java.util.Optional;
import java.util.logging.Level; import java.util.logging.Level;
...@@ -22,7 +22,7 @@ import java.util.logging.Logger; ...@@ -22,7 +22,7 @@ import java.util.logging.Logger;
public class SubmissionSubscriber implements Subscriber { public class SubmissionSubscriber implements Subscriber {
private static final Logger logger = SdkLogger.defaultLogger(FitCoAuthService.class); private static final Logger logger = SdkLogger.defaultLogger(MonoPublisherOAuthService.class);
private final OAuthService authService; private final OAuthService authService;
private final CryptoService cryptoService; private final CryptoService cryptoService;
......
package fitconnect.impl.auth; package fitconnect.impl.auth;
import com.fasterxml.jackson.databind.ObjectMapper;
import fitconnect.api.services.auth.OAuthService;
import fitconnect.api.domain.auth.OAuthToken; import fitconnect.api.domain.auth.OAuthToken;
import fitconnect.api.exceptions.AuthenticationException; import fitconnect.api.exceptions.AuthenticationException;
import fitconnect.api.services.auth.OAuthService;
import fitconnect.impl.logger.SdkLogger; import fitconnect.impl.logger.SdkLogger;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.io.IOException; import java.nio.charset.StandardCharsets;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.logging.Level; import java.util.List;
import java.util.logging.Logger; import java.util.logging.Logger;
import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.joining;
public class FitCoAuthService implements OAuthService { public class MonoPublisherOAuthService implements OAuthService {
private static final Logger logger = SdkLogger.defaultLogger(FitCoAuthService.class); private static final Logger logger = SdkLogger.defaultLogger(MonoPublisherOAuthService.class);
private static final ObjectMapper mapper = new ObjectMapper();
private final HttpClient client;
private final String tokenUrl; private final String tokenUrl;
public FitCoAuthService(final HttpClient client, final String tokenUrl) { public MonoPublisherOAuthService(final String tokenUrl) {
this.client = client;
this.tokenUrl = tokenUrl; this.tokenUrl = tokenUrl;
} }
@Override @Override
public OAuthToken authenticate(String clientId, String clientSecret, String... scope) throws AuthenticationException { public OAuthToken authenticate(String clientId, String clientSecret, String... scope) throws AuthenticationException {
final String requestBody = buildRequestBody(clientId, clientSecret, scope); final String requestBody = buildRequestBody(clientId, clientSecret, scope);
try {
return performTokenRequest(requestBody); return performTokenRequestAsync(requestBody).block();
} catch (IOException | InterruptedException e) {
logger.log(Level.SEVERE, "error retrieving access token", e);
throw new AuthenticationException(e.getMessage(),e);
}
} }
private String buildRequestBody(String clientId, String clientSecret, String... scope) { private String buildRequestBody(String clientId, String clientSecret, String... scope) {
...@@ -51,20 +44,25 @@ public class FitCoAuthService implements OAuthService { ...@@ -51,20 +44,25 @@ public class FitCoAuthService implements OAuthService {
Arrays.stream(scope).forEach(s -> data.put("scope", s)); Arrays.stream(scope).forEach(s -> data.put("scope", s));
return data.entrySet() return data.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(joining("&"));
.stream()
.map(e -> e.getKey() + "=" + e.getValue())
.collect(joining("&"));
} }
private OAuthToken performTokenRequest(final String requestBody) throws IOException, InterruptedException { // TODO generalize HTTP requests in separate common service
HttpRequest request = HttpRequest.newBuilder() private Mono<OAuthToken> performTokenRequestAsync(final String requestBody){
.header("Accept", "application/json") return WebClient.builder()
.header("Content-Type","application/x-www-form-urlencoded;charset=UTF-8") .defaultHeaders(this::setHeaders)
.uri(URI.create(tokenUrl)) .build()
.POST(HttpRequest.BodyPublishers.ofString(requestBody)) .post()
.build(); .uri(tokenUrl)
var responseBody = client.send(request, HttpResponse.BodyHandlers.ofString()).body(); .bodyValue(requestBody)
return mapper.readValue(responseBody,OAuthToken.class); .retrieve()
.bodyToMono(OAuthToken.class);
} }
private void setHeaders(HttpHeaders headers) {
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.setAcceptCharset(List.of(StandardCharsets.UTF_8));
}
} }
package fitconnect.impl.auth; package fitconnect.impl.auth;
import fitconnect.api.services.Sender;
import fitconnect.api.domain.auth.OAuthToken; import fitconnect.api.domain.auth.OAuthToken;
import fitconnect.api.services.Sender;
import fitconnect.impl.SubmissionSender; import fitconnect.impl.SubmissionSender;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.net.http.HttpClient;
import java.util.Optional; import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
...@@ -21,8 +20,7 @@ class OAuthTokenIntegrationTest { ...@@ -21,8 +20,7 @@ class OAuthTokenIntegrationTest {
var secret = "PnzR8Vbmhpv_VwTkT34wponqXWK8WBm-LADlryYdV4o"; var secret = "PnzR8Vbmhpv_VwTkT34wponqXWK8WBm-LADlryYdV4o";
var scope = "send:region:DE"; var scope = "send:region:DE";
var httpClient = HttpClient.newHttpClient(); var authService = new MonoPublisherOAuthService(tokenUrl);
var authService = new FitCoAuthService(httpClient, tokenUrl);
final Sender sender = new SubmissionSender(authService, null, null); final Sender sender = new SubmissionSender(authService, null, null);
// When // When
......
...@@ -73,6 +73,11 @@ ...@@ -73,6 +73,11 @@
<artifactId>everit-json-schema</artifactId> <artifactId>everit-json-schema</artifactId>
<version>1.14.1</version> <version>1.14.1</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.7.0</version>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment