fixed streaming download for SEB Log export

This commit is contained in:
anhefti 2021-12-01 13:49:48 +01:00
parent f44c82bde3
commit 614f4430d2
6 changed files with 81 additions and 32 deletions

View file

@ -55,26 +55,32 @@ public class SEBClientLogExport extends AbstractDownloadServiceHandler {
queryParams.add(param, String.valueOf(request.getParameter(param)));
}
final InputStream input = this.restService
this.restService
.getBuilder(ExportSEBClientLogs.class)
.withResponseExtractor(response -> {
try {
final InputStream input = response.getBody();
IOUtils.copyLarge(input, downloadOut);
} catch (final IOException e) {
log.error(
"Unexpected error while streaming incoming config data from web-service to output-stream of download response: ",
e);
} finally {
try {
downloadOut.flush();
downloadOut.close();
} catch (final IOException e) {
log.error("Unexpected error while trying to close download output-stream");
}
}
return true;
})
.withQueryParams(queryParams)
.call()
.getOrThrow();
.onError(error -> log.error("Download failed: ", error));
try {
IOUtils.copyLarge(input, downloadOut);
} catch (final IOException e) {
log.error(
"Unexpected error while streaming incoming config data from web-service to output-stream of download response: ",
e);
} finally {
try {
downloadOut.flush();
downloadOut.close();
} catch (final IOException e) {
log.error("Unexpected error while trying to close download output-stream");
}
}
}
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequest;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.util.Result;
public class AbstractDownloadCall extends RestCall<Boolean> {
protected AbstractDownloadCall(
final MediaType contentType,
final String path) {
super(new RestCall.TypeKey<>(CallType.UNDEFINED, null, new TypeReference<Boolean>() {
}), HttpMethod.GET, contentType, path);
}
@Override
protected Result<Boolean> exchange(final RestCallBuilder builder) {
return Result.tryCatch(() -> builder
.getRestTemplate()
.execute(
builder.buildURI(),
this.httpMethod,
(final ClientHttpRequest requestCallback) -> {
},
builder.getResponseExtractor(),
builder.getURIVariables()));
}
}

View file

@ -17,6 +17,7 @@ import org.springframework.http.client.ClientHttpRequest;
import ch.ethz.seb.sebserver.gbl.util.Result;
@Deprecated(since = "1.2. : This is not streaming correctly. Use AbstractDownloadCall instead")
public abstract class AbstractExportCall extends RestCall<InputStream> {
protected AbstractExportCall(

View file

@ -29,6 +29,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
@ -224,6 +225,7 @@ public abstract class RestCall<T> {
private final HttpHeaders httpHeaders;
private String body = null;
private InputStream streamingBody = null;
private ResponseExtractor<Boolean> responseExtractor = null;
private final MultiValueMap<String, String> queryParams;
private final Map<String, String> uriVariables;
@ -253,6 +255,15 @@ public abstract class RestCall<T> {
return this.restTemplate;
}
public RestCallBuilder withResponseExtractor(final ResponseExtractor<Boolean> responseExtractor) {
this.responseExtractor = responseExtractor;
return this;
}
public ResponseExtractor<Boolean> getResponseExtractor() {
return this.responseExtractor;
}
public RestCallBuilder withRestTemplate(final RestTemplate restTemplate) {
this.restTemplate = restTemplate;
return this;

View file

@ -8,33 +8,21 @@
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam;
import java.io.InputStream;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.AbstractExportCall;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.AbstractDownloadCall;
@Lazy
@Component
@GuiProfile
public class ExportSEBClientLogs extends AbstractExportCall {
public class ExportSEBClientLogs extends AbstractDownloadCall {
public ExportSEBClientLogs() {
super(new TypeKey<>(
CallType.UNDEFINED,
EntityType.CLIENT_EVENT,
new TypeReference<InputStream>() {
}),
HttpMethod.GET,
MediaType.APPLICATION_FORM_URLENCODED,
super(MediaType.APPLICATION_FORM_URLENCODED,
API.SEB_CLIENT_EVENT_ENDPOINT
+ API.SEB_CLIENT_EVENT_EXPORT_PATH_SEGMENT);
}

View file

@ -225,7 +225,7 @@ public class SEBClientEventAdminServiceImpl implements SEBClientEventAdminServic
private final String sort;
private int pageNumber = 1;
private final int pageSize = 1000;
private final int pageSize = 10000;
private Collection<ClientEventRecord> nextRecords;