Skip to content

Commit

Permalink
Adds several improvements in the resources handling
Browse files Browse the repository at this point in the history
- Added explicit setting of the ``UTF-8`` for the IO operations with
streams. There are some utility libraries, which are using different
default charset, which may lead to errors or unexpected behavior.
- Added explicit resource closing for all streams that we process in
some way. There were few places, where the streams were not properly
closed, which may cause memory leaks and OOM exception.
- Introduced additional return types for the result of RDF exports. Now
the result can be returned as ``File``, ``Stream`` or ``String``. This
will allow to avoid OOM exception, while buffering large data as String,
which was the previous behavior. The user may control the return type by
providing additional setting to the ``ResultFormat``, when building the
command.
- Prepared the library for the patch release ``1.6.2``.
  • Loading branch information
tonyKunchev committed May 12, 2022
1 parent 7b7f481 commit 0a5a4c0
Show file tree
Hide file tree
Showing 23 changed files with 271 additions and 100 deletions.
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
# Ontotext OntoRefine Client Library

## Version 1.7
## Version 1.6.2

### New

- Introduced additional return types for the SPARQL based RDF export. Previously the result was returned only as ``String``. There are cases, where the produced RDF
is quite large and if there is no enough memory to for buffering, the command throws OOM exception, while consuming the stream. With the additional types the users
can avoid that problem by writing the stream in the file or directly consuming it from the response object.
The return types are also applied for the default command for RDF export, which uses the mapping JSON from the generated from the Mapping UI.
The users can control the return type by providing different ``ResultType`` to the ``ResultFormat#as(ResultType)``. The default is ``STRING`` to keep the
library compatible and to ease the migration effort.

### Changes

- All stream IO operations are now done in ``UTF-8``. There are some utility libraries that have different default charset. To keep the library consistent and
the behavior predictable, we explicitly set the charset to ``UTF-8``.

### Bug fixes

- There were places, where some of the streams were not closed properly, which may cause memory leaks in specific cases. To ensure that the resources are handled
correctly, we've updated the logic to explicitly close all of the streams that we touch.


## Version 1.6.1

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ complete given operation.
<dependency>
<groupId>com.ontotext</groupId>
<artifactId>ontorefine-client</artifactId>
<version>1.6.1</version>
<version>1.6.2</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<groupId>com.ontotext</groupId>
<artifactId>ontorefine-client</artifactId>
<version>1.7.0-SNAPSHOT</version>
<version>1.6.2</version>

<name>${project.groupId}:${project.artifactId}</name>
<description>An OntoRefine Client Library</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.ontotext.refine.client.util.HttpParser.HTTP_PARSER;
import static com.ontotext.refine.client.util.JsonParser.JSON_PARSER;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.commons.lang3.Validate.notBlank;
import static org.apache.commons.lang3.Validate.notNull;
import static org.apache.http.HttpHeaders.ACCEPT;
Expand All @@ -16,7 +17,6 @@
import java.util.Collections;
import java.util.List;
import java.util.StringJoiner;
import org.apache.http.Consts;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
Expand All @@ -25,7 +25,6 @@
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;


/**
* A command to preview expressions on a project.
*/
Expand Down Expand Up @@ -82,7 +81,8 @@ public ExpressionPreviewResponse execute(RefineClient client) throws RefineExcep
.post(client.createUri(endpoint()))
.addParameter(Constants.CSRF_TOKEN, token)
.setHeader(ACCEPT, APPLICATION_JSON.getMimeType())
.setEntity(new UrlEncodedFormEntity(form, Consts.UTF_8))
.setEntity(new UrlEncodedFormEntity(form,
UTF_8))
.build();

return client.execute(request, this);
Expand All @@ -97,7 +97,7 @@ public ExpressionPreviewResponse execute(RefineClient client) throws RefineExcep
@Override
public ExpressionPreviewResponse handleResponse(HttpResponse response) throws IOException {
HTTP_PARSER.assureStatusCode(response, SC_OK);
String responseBody = EntityUtils.toString(response.getEntity());
String responseBody = EntityUtils.toString(response.getEntity(), UTF_8);
return parseExpressionPreviewResponse(responseBody);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.ontotext.refine.client.util.HttpParser.HTTP_PARSER;
import static com.ontotext.refine.client.util.JsonParser.JSON_PARSER;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.commons.lang3.Validate.notBlank;
import static org.apache.http.HttpHeaders.ACCEPT;
import static org.apache.http.HttpStatus.SC_OK;
Expand All @@ -17,7 +18,6 @@
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;


/**
* A command to retrieve project meta data.
*/
Expand Down Expand Up @@ -52,7 +52,7 @@ public GetProjectMetadataResponse execute(RefineClient client) throws RefineExce
@Override
public GetProjectMetadataResponse handleResponse(HttpResponse response) throws IOException {
HTTP_PARSER.assureStatusCode(response, SC_OK);
String responseBody = EntityUtils.toString(response.getEntity());
String responseBody = EntityUtils.toString(response.getEntity(), UTF_8);
return new GetProjectMetadataResponse(JSON_PARSER.read(responseBody, ProjectMetadata.class));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.ontotext.refine.client.util.HttpParser.HTTP_PARSER;
import static com.ontotext.refine.client.util.JsonParser.JSON_PARSER;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.http.HttpHeaders.ACCEPT;
import static org.apache.http.HttpStatus.SC_OK;
import static org.apache.http.entity.ContentType.APPLICATION_JSON;
Expand Down Expand Up @@ -51,7 +52,7 @@ public GetCsrfTokenResponse execute(RefineClient client) throws RefineException
@Override
public GetCsrfTokenResponse handleResponse(HttpResponse response) throws IOException {
HTTP_PARSER.assureStatusCode(response, SC_OK);
String responseBody = EntityUtils.toString(response.getEntity());
String responseBody = EntityUtils.toString(response.getEntity(), UTF_8);
return parseGetCsrfTokenResponse(responseBody);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.ontotext.refine.client.util.HttpParser.HTTP_PARSER;
import static com.ontotext.refine.client.util.JsonParser.JSON_PARSER;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Collections.singletonList;
import static org.apache.commons.lang3.Validate.notBlank;
import static org.apache.http.HttpHeaders.ACCEPT;
Expand All @@ -13,15 +14,13 @@
import com.ontotext.refine.client.command.RefineCommand;
import com.ontotext.refine.client.exceptions.RefineException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.http.HttpResponse;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;


/**
* A command to delete a project.
*/
Expand Down Expand Up @@ -50,7 +49,7 @@ public String endpoint() {
public DeleteProjectResponse execute(RefineClient client) throws RefineException {
try {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(
singletonList(new BasicNameValuePair("project", projectId)), StandardCharsets.UTF_8);
singletonList(new BasicNameValuePair("project", projectId)), UTF_8);

HttpUriRequest request = RequestBuilder
.post(client.createUri(endpoint()))
Expand All @@ -70,7 +69,7 @@ public DeleteProjectResponse execute(RefineClient client) throws RefineException
@Override
public DeleteProjectResponse handleResponse(HttpResponse response) throws IOException {
HTTP_PARSER.assureStatusCode(response, SC_OK);
String responseBody = EntityUtils.toString(response.getEntity());
String responseBody = EntityUtils.toString(response.getEntity(), UTF_8);
return parseDeleteProjectResponse(responseBody);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.ontotext.refine.client.exceptions.RefineException;
import com.ontotext.refine.client.util.HttpParser;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import org.apache.commons.lang3.Validate;
import org.apache.http.HttpResponse;
Expand Down Expand Up @@ -49,8 +50,9 @@ public GetProjectModelsResponse execute(RefineClient client) throws RefineExcept
@Override
public GetProjectModelsResponse handleResponse(HttpResponse response) throws IOException {
HttpParser.HTTP_PARSER.assureStatusCode(response, HttpStatus.SC_OK);
return new JsonMapper()
.readValue(response.getEntity().getContent(), GetProjectModelsResponse.class);
try (InputStream stream = response.getEntity().getContent()) {
return new JsonMapper().readValue(stream, GetProjectModelsResponse.class);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.ontotext.refine.client.util.HttpParser.HTTP_PARSER;
import static com.ontotext.refine.client.util.JsonParser.JSON_PARSER;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.commons.lang3.StringUtils.appendIfMissing;
import static org.apache.commons.lang3.StringUtils.prependIfMissing;
import static org.apache.commons.lang3.Validate.noNullElements;
Expand All @@ -23,7 +24,6 @@
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.http.Consts;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
Expand Down Expand Up @@ -75,7 +75,7 @@ public ApplyOperationsResponse execute(RefineClient client) throws RefineExcepti
String opsAsJsonArray = appendIfMissing(prependIfMissing(ops, "["), "]");
form.add(new BasicNameValuePair("operations", opsAsJsonArray));

UrlEncodedFormEntity entity = new UrlEncodedFormEntity(form, Consts.UTF_8);
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(form, UTF_8);

HttpUriRequest request = RequestBuilder
.post(client.createUri(endpoint()))
Expand All @@ -97,7 +97,7 @@ public ApplyOperationsResponse execute(RefineClient client) throws RefineExcepti
@Override
public ApplyOperationsResponse handleResponse(HttpResponse response) throws IOException {
HTTP_PARSER.assureStatusCode(response, SC_OK);
String responseBody = EntityUtils.toString(response.getEntity());
String responseBody = EntityUtils.toString(response.getEntity(), UTF_8);
return parseApplyOperationsResponse(responseBody);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
import com.ontotext.refine.client.exceptions.RefineException;
import com.ontotext.refine.client.util.HttpParser;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.commons.lang3.Validate;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;


/**
* A command that retrieves the operations history for specified project.
*
Expand Down Expand Up @@ -53,12 +53,14 @@ public GetOperationsResponse execute(RefineClient client) throws RefineException
@Override
public GetOperationsResponse handleResponse(HttpResponse response) throws IOException {
HttpParser.HTTP_PARSER.assureStatusCode(response, HttpStatus.SC_OK);
JsonMapper mapper = new JsonMapper();
JsonNode responseJson = mapper.readTree(response.getEntity().getContent());
List<JsonNode> operations = responseJson.findValues("operation");
return new GetOperationsResponse()
.setContent(mapper.createArrayNode().addAll(operations))
.setProject(project);
try (InputStream stream = response.getEntity().getContent()) {
JsonMapper mapper = new JsonMapper();
JsonNode responseJson = mapper.readTree(stream);
List<JsonNode> operations = responseJson.findValues("operation");
return new GetOperationsResponse()
.setContent(mapper.createArrayNode().addAll(operations))
.setProject(project);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
import com.ontotext.refine.client.command.RefineCommand;
import com.ontotext.refine.client.exceptions.RefineException;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.lang3.Validate;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;


/**
* A command to retrieve the preference for specific property.
*
Expand Down Expand Up @@ -50,8 +50,10 @@ public GetPreferenceCommandResponse execute(RefineClient client) throws RefineEx
@Override
public GetPreferenceCommandResponse handleResponse(HttpResponse response) throws IOException {
HTTP_PARSER.assureStatusCode(response, HttpStatus.SC_OK);
JsonNode json = JSON_PARSER.parseJson(response.getEntity().getContent());
return new GetPreferenceCommandResponse(json);
try (InputStream stream = response.getEntity().getContent()) {
JsonNode json = JSON_PARSER.parseJson(stream);
return new GetPreferenceCommandResponse(json);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

import static com.ontotext.refine.client.util.HttpParser.HTTP_PARSER;
import static com.ontotext.refine.client.util.JsonParser.JSON_PARSER;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.fasterxml.jackson.databind.JsonNode;
import com.ontotext.refine.client.RefineClient;
import com.ontotext.refine.client.command.RefineCommand;
import com.ontotext.refine.client.exceptions.RefineException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.Validate;
Expand All @@ -20,7 +21,6 @@
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.message.BasicNameValuePair;


/**
* A command to set preference for specific property.
*
Expand Down Expand Up @@ -53,7 +53,7 @@ public SetPreferenceCommandResponse execute(RefineClient client) throws RefineEx
HttpUriRequest request = RequestBuilder
.post(client.createUri(endpoint()))
.addParameter("name", property)
.setEntity(new UrlEncodedFormEntity(form, StandardCharsets.UTF_8))
.setEntity(new UrlEncodedFormEntity(form, UTF_8))
.build();

return client.execute(request, this);
Expand All @@ -70,18 +70,20 @@ public SetPreferenceCommandResponse execute(RefineClient client) throws RefineEx
@Override
public SetPreferenceCommandResponse handleResponse(HttpResponse response) throws IOException {
HTTP_PARSER.assureStatusCode(response, HttpStatus.SC_OK);
JsonNode node = JSON_PARSER.parseJson(response.getEntity().getContent());
String code = JSON_PARSER.findExistingPath(node, "code").asText();
switch (code) {
case "ok":
return SetPreferenceCommandResponse.ok();
case "error":
String message = JSON_PARSER.findExistingPath(node, "message").asText();
return SetPreferenceCommandResponse.error(message);
default:
throw new RefineException(
"Failed to parse the response from the set preference operation for property: %s",
property);
try (InputStream stream = response.getEntity().getContent()) {
JsonNode node = JSON_PARSER.parseJson(stream);
String code = JSON_PARSER.findExistingPath(node, "code").asText();
switch (code) {
case "ok":
return SetPreferenceCommandResponse.ok();
case "error":
String message = JSON_PARSER.findExistingPath(node, "message").asText();
return SetPreferenceCommandResponse.error(message);
default:
throw new RefineException(
"Failed to parse the response from the set preference operation for property: %s",
property);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
import com.ontotext.refine.client.util.HttpParser;
import com.ontotext.refine.client.util.JsonParser;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Collection;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;


/**
* A command for retrieving the processes that are currently running for project.
*
Expand All @@ -27,7 +27,7 @@
public class GetProcessesCommand implements RefineCommand<GetProcessesCommandResponse> {

private static final TypeReference<Collection<ProjectProcess>> PROCESSES_TYPE =
new TypeReference<Collection<ProjectProcess>>() {};
new TypeReference<>() {};

private final String project;

Expand Down Expand Up @@ -60,10 +60,12 @@ public GetProcessesCommandResponse execute(RefineClient client) throws RefineExc
@Override
public GetProcessesCommandResponse handleResponse(HttpResponse response) throws IOException {
HttpParser.HTTP_PARSER.assureStatusCode(response, HttpStatus.SC_OK);
JsonNode json = JsonParser.JSON_PARSER.parseJson(response.getEntity().getContent());
Collection<ProjectProcess> processes =
JsonParser.JSON_PARSER.read(json.findValue("processes").toString(), PROCESSES_TYPE);
return new GetProcessesCommandResponse(processes);
try (InputStream stream = response.getEntity().getContent()) {
JsonNode json = JsonParser.JSON_PARSER.parseJson(stream);
Collection<ProjectProcess> processes =
JsonParser.JSON_PARSER.read(json.findValue("processes").toString(), PROCESSES_TYPE);
return new GetProcessesCommandResponse(processes);
}
}

/**
Expand Down
Loading

0 comments on commit 0a5a4c0

Please sign in to comment.