From e5657dbe8cb0dc860b77ee0f53e52a07ff77874f Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Wed, 6 Nov 2024 17:46:44 +0100 Subject: [PATCH 01/19] :sparkles: add support for workflow enqueuing --- src/main/java/com/mindee/http/MindeeApi.java | 7 ++ .../java/com/mindee/http/MindeeHttpApi.java | 78 +++++++++++++++-- .../com/mindee/parsing/common/ApiObject.java | 46 ++++++++++ .../com/mindee/parsing/common/Execution.java | 85 +++++++++++++++++++ .../mindee/parsing/common/ExecutionFile.java | 30 +++++++ .../java/com/mindee/parsing/common/Job.java | 19 ++--- .../parsing/common/WorkflowResponse.java | 21 +++++ 7 files changed, 265 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/mindee/parsing/common/ApiObject.java create mode 100644 src/main/java/com/mindee/parsing/common/Execution.java create mode 100644 src/main/java/com/mindee/parsing/common/ExecutionFile.java create mode 100644 src/main/java/com/mindee/parsing/common/WorkflowResponse.java diff --git a/src/main/java/com/mindee/http/MindeeApi.java b/src/main/java/com/mindee/http/MindeeApi.java index 080197b0c..35e6545a6 100644 --- a/src/main/java/com/mindee/http/MindeeApi.java +++ b/src/main/java/com/mindee/http/MindeeApi.java @@ -3,6 +3,7 @@ import com.mindee.parsing.common.AsyncPredictResponse; import com.mindee.parsing.common.Inference; import com.mindee.parsing.common.PredictResponse; +import com.mindee.parsing.common.WorkflowResponse; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.apache.http.HttpEntity; @@ -39,6 +40,12 @@ abstract public PredictResponse predictPost( RequestParameters requestParameters ) throws IOException; + abstract public WorkflowResponse executeWorkflowPost( + Class documentClass, + String workflowId, + RequestParameters requestParameters + ) throws IOException; + protected String getUserAgent() { String javaVersion = System.getProperty("java.version"); String sdkVersion = getClass().getPackage().getImplementationVersion(); diff --git a/src/main/java/com/mindee/http/MindeeHttpApi.java b/src/main/java/com/mindee/http/MindeeHttpApi.java index 6ff49378c..e8c44c689 100644 --- a/src/main/java/com/mindee/http/MindeeHttpApi.java +++ b/src/main/java/com/mindee/http/MindeeHttpApi.java @@ -10,6 +10,7 @@ import com.mindee.parsing.common.ErrorDetails; import com.mindee.parsing.common.Inference; import com.mindee.parsing.common.PredictResponse; +import com.mindee.parsing.common.WorkflowResponse; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; @@ -41,6 +42,7 @@ public final class MindeeHttpApi extends MindeeApi { private static final ObjectMapper mapper = new ObjectMapper(); private final Function buildBaseUrl = this::buildUrl; + private final Function buildWorkflowBaseUrl = this::buildWorkflowUrl; /** * The MindeeSetting needed to make the api call. */ @@ -51,27 +53,35 @@ public final class MindeeHttpApi extends MindeeApi { */ private final HttpClientBuilder httpClientBuilder; /** - * The function used to generate the API endpoint URL. Only needs to be set if the api calls need - * to be directed through internal URLs. + * The function used to generate the API endpoint URL. + * Only needs to be set if the api calls need to be directed through internal URLs. */ private final Function urlFromEndpoint; + /** - * The function used to generate the API endpoint URL for Async calls. Only needs to be set if the - * api calls need to be directed through internal URLs. + * The function used to generate the API endpoint URL for workflow execution calls. + * Only needs to be set if the api calls need to be directed through internal URLs. */ private final Function asyncUrlFromEndpoint; /** - * The function used to generate the Job status URL for Async calls. Only needs to be set if the - * api calls need to be directed through internal URLs. + * The function used to generate the Job status URL for Async calls. + * Only needs to be set if the api calls need to be directed through internal URLs. */ private final Function documentUrlFromEndpoint; + /** + * The function used to generate the Job status URL for Async calls. + * Only needs to be set if the api calls need to be directed through internal URLs. + */ + private final Function workflowUrlFromId; + public MindeeHttpApi(MindeeSettings mindeeSettings) { this( mindeeSettings, null, null, null, + null, null ); } @@ -82,7 +92,8 @@ private MindeeHttpApi( HttpClientBuilder httpClientBuilder, Function urlFromEndpoint, Function asyncUrlFromEndpoint, - Function documentUrlFromEndpoint + Function documentUrlFromEndpoint, + Function workflowUrlFromEndpoint ) { this.mindeeSettings = mindeeSettings; @@ -110,6 +121,13 @@ private MindeeHttpApi( this.documentUrlFromEndpoint = this.buildBaseUrl.andThen( (url) -> url.concat("/documents/queue/")); } + + if (workflowUrlFromEndpoint != null) { + this.workflowUrlFromId = workflowUrlFromEndpoint; + } else { + this.workflowUrlFromId = this.buildWorkflowBaseUrl.andThen( + (url) -> url); + } } /** @@ -243,6 +261,48 @@ public AsyncPredictResponse predictAsyncPost( } } + + /** + * POST a prediction request for a workflow response. + */ + public WorkflowResponse executeWorkflowPost( + Class documentClass, + String workflowId, + RequestParameters requestParameters + ) throws IOException { + + String url = workflowUrlFromId.apply(workflowId); + HttpPost post = buildHttpPost(url, requestParameters); + + // required to register jackson date module format to deserialize + mapper.findAndRegisterModules(); + JavaType parametricType = mapper.getTypeFactory().constructParametricType( + WorkflowResponse.class, + documentClass + ); + try ( + CloseableHttpClient httpClient = httpClientBuilder.build(); + CloseableHttpResponse response = httpClient.execute(post) + ) { + HttpEntity responseEntity = response.getEntity(); + int statusCode = response.getStatusLine().getStatusCode(); + if (!is2xxStatusCode(statusCode)) { + throw getHttpError(parametricType, response); + } + if (responseEntity.getContentLength() == 0) { + throw new MindeeException("Empty response from server."); + } + String rawResponse = readRawResponse(responseEntity); + WorkflowResponse mappedResponse = mapper.readValue(rawResponse, parametricType); + mappedResponse.setRawResponse(rawResponse); + return mappedResponse; + } catch (IOException err) { + throw new MindeeException(err.getMessage(), err); + } + } + + + private MindeeHttpException getHttpError( JavaType parametricType, CloseableHttpResponse response @@ -289,6 +349,10 @@ private String buildUrl(Endpoint endpoint) { + endpoint.getVersion(); } + private String buildWorkflowUrl(String workflowId) { + return this.mindeeSettings.getBaseUrl() + "/workflows/" + workflowId + "/executions"; + } + private HttpPost buildHttpPost( String url, RequestParameters requestParameters diff --git a/src/main/java/com/mindee/parsing/common/ApiObject.java b/src/main/java/com/mindee/parsing/common/ApiObject.java new file mode 100644 index 000000000..4d682fc17 --- /dev/null +++ b/src/main/java/com/mindee/parsing/common/ApiObject.java @@ -0,0 +1,46 @@ +package com.mindee.parsing.common; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.TemporalAccessor; + +/** + * Interface to help deserialize http datetime objects in a similar fashion. + */ +public interface ApiObject { + /** + * Deserializer for LocalDateTime. + */ + class LocalDateTimeDeserializer extends JsonDeserializer { + + @Override + public LocalDateTime deserialize( + JsonParser jsonParser, + DeserializationContext deserializationContext) throws IOException { + DateTimeFormatter formatter = new DateTimeFormatterBuilder() + .parseCaseInsensitive() + .append(DateTimeFormatter.ISO_LOCAL_DATE) + .appendLiteral('T') + .append(DateTimeFormatter.ISO_LOCAL_TIME) + .optionalStart() + .appendOffsetId() + .toFormatter(); + String dateString = jsonParser.getValueAsString(); + TemporalAccessor temporalAccessor = formatter.parseBest(dateString, ZonedDateTime::from, + LocalDateTime::from); + if (temporalAccessor instanceof ZonedDateTime) { + return ((ZonedDateTime) temporalAccessor).withZoneSameInstant(ZoneOffset.UTC) + .toLocalDateTime(); + } else { + return ((LocalDateTime) temporalAccessor); + } + } + } +} diff --git a/src/main/java/com/mindee/parsing/common/Execution.java b/src/main/java/com/mindee/parsing/common/Execution.java new file mode 100644 index 000000000..ebcbbf359 --- /dev/null +++ b/src/main/java/com/mindee/parsing/common/Execution.java @@ -0,0 +1,85 @@ +package com.mindee.parsing.common; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.mindee.product.generated.GeneratedV1Document; +import java.time.LocalDateTime; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * Representation of a workflow execution. + */ +@Getter +@EqualsAndHashCode +@JsonIgnoreProperties(ignoreUnknown = true) +@AllArgsConstructor +@NoArgsConstructor +public class Execution implements ApiObject { + /** + * Identifier for the execution. + */ + @JsonProperty("id") + private String id; + + /** + * Identifier for the workflow. + */ + @JsonProperty("workflow_id") + private String workflowId; + + /** + * The time at which the execution started. + */ + @JsonProperty("created_at") + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime createdAt; + + /** + * The time at which the file was uploaded to a workflow. + */ + @JsonProperty("uploaded_at") + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime availableAt; + + /** + * The time at which the file was tagged as reviewed. + */ + @JsonProperty("reviewed_at") + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime reviewedAt; + + /** + * Execution Status. + */ + @JsonProperty("status") + private String status; + + /** + * Execution type. + */ + @JsonProperty("type") + private String type; + + /** + * Information about an error that occurred during the job processing. + */ + @JsonProperty("error") + private Error error; + + + /** + * Deserialized inference object. + */ + @JsonProperty("inference") + private DocT inference; + + /** + * Reviewed fields and values. + */ + @JsonProperty("reviewed_prediction") + private GeneratedV1Document reviewedPrediction; +} diff --git a/src/main/java/com/mindee/parsing/common/ExecutionFile.java b/src/main/java/com/mindee/parsing/common/ExecutionFile.java new file mode 100644 index 000000000..af51bba90 --- /dev/null +++ b/src/main/java/com/mindee/parsing/common/ExecutionFile.java @@ -0,0 +1,30 @@ +package com.mindee.parsing.common; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * Representation of a workflow execution's file data. + */ +@Getter +@EqualsAndHashCode +@JsonIgnoreProperties(ignoreUnknown = true) +@AllArgsConstructor +@NoArgsConstructor +public class ExecutionFile { + /** + * File name. + */ + @JsonProperty("name") + private String name; + + /** + * Identifier for the execution. + */ + @JsonProperty("alias") + private String alias; +} diff --git a/src/main/java/com/mindee/parsing/common/Job.java b/src/main/java/com/mindee/parsing/common/Job.java index 6e6a1213c..087899b6c 100644 --- a/src/main/java/com/mindee/parsing/common/Job.java +++ b/src/main/java/com/mindee/parsing/common/Job.java @@ -2,17 +2,8 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import java.io.IOException; import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.temporal.TemporalAccessor; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -26,30 +17,30 @@ @JsonIgnoreProperties(ignoreUnknown = true) @AllArgsConstructor @NoArgsConstructor -public class Job { +public class Job implements ApiObject{ /** - * The time at which the job finished + * The time at which the job finished. */ @JsonProperty("available_at") @JsonDeserialize(using = LocalDateTimeDeserializer.class) private LocalDateTime availableAt; /** - * Identifier for the job + * Identifier for the job. */ @JsonProperty("id") private String id; /** - * The time at which the job started + * The time at which the job started. */ @JsonProperty("issued_at") @JsonDeserialize(using = LocalDateTimeDeserializer.class) private LocalDateTime issuedAt; /** - * Job Status + * Job Status. */ @JsonProperty("status") private String status; diff --git a/src/main/java/com/mindee/parsing/common/WorkflowResponse.java b/src/main/java/com/mindee/parsing/common/WorkflowResponse.java new file mode 100644 index 000000000..5ffe2f5ed --- /dev/null +++ b/src/main/java/com/mindee/parsing/common/WorkflowResponse.java @@ -0,0 +1,21 @@ +package com.mindee.parsing.common; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * Represents the server response after a document is sent to a workflow. + */ +@Data +@EqualsAndHashCode(callSuper = true) +@JsonIgnoreProperties(ignoreUnknown = true) +public class WorkflowResponse extends ApiResponse { + /** + * Set the prediction model used to parse the document. + * The response object will be instantiated based on this parameter. + */ + @JsonProperty("execution") + Execution execution; +} From 15eb9a757aef2b9899a62721fb1e97cf7b99d510 Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Thu, 7 Nov 2024 11:27:43 +0100 Subject: [PATCH 02/19] bump test lib --- src/main/java/com/mindee/http/MindeeHttpApi.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/mindee/http/MindeeHttpApi.java b/src/main/java/com/mindee/http/MindeeHttpApi.java index e8c44c689..b4648aca5 100644 --- a/src/main/java/com/mindee/http/MindeeHttpApi.java +++ b/src/main/java/com/mindee/http/MindeeHttpApi.java @@ -125,8 +125,7 @@ private MindeeHttpApi( if (workflowUrlFromEndpoint != null) { this.workflowUrlFromId = workflowUrlFromEndpoint; } else { - this.workflowUrlFromId = this.buildWorkflowBaseUrl.andThen( - (url) -> url); + this.workflowUrlFromId = this.buildWorkflowBaseUrl; } } From 3f4c5f97443b087f32976d7e9877218e2abc226c Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Tue, 12 Nov 2024 13:56:51 +0100 Subject: [PATCH 03/19] tempsave --- .../parsing/common/WorkflowResponseTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/java/com/mindee/parsing/common/WorkflowResponseTest.java diff --git a/src/test/java/com/mindee/parsing/common/WorkflowResponseTest.java b/src/test/java/com/mindee/parsing/common/WorkflowResponseTest.java new file mode 100644 index 000000000..6f5856f37 --- /dev/null +++ b/src/test/java/com/mindee/parsing/common/WorkflowResponseTest.java @@ -0,0 +1,21 @@ +package com.mindee.parsing.common; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.mindee.product.invoicesplitter.InvoiceSplitterV1; +import java.io.File; +import java.io.IOException; + +public class WorkflowResponseTest { + private WorkflowResponse loadWorkflowResponse(String filePath) throws + IOException { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.findAndRegisterModules(); + + JavaType type = objectMapper.getTypeFactory().constructParametricType( + WorkflowResponse.class, + InvoiceSplitterV1.class + ); + return objectMapper.readValue(new File(filePath), type); + } +} From f69b1b21bc2c17c7e187d450cf080859744a37c1 Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Wed, 13 Nov 2024 15:25:12 +0100 Subject: [PATCH 04/19] add micro-test --- docs/code_samples/workflow_execution.txt | 29 +++++++++ src/main/java/com/mindee/MindeeClient.java | 35 +++++++++++ .../parsing/common/WorkflowResponse.java | 4 ++ .../com/mindee/workflow/WorkflowTest.java | 61 +++++++++++++++++++ tests/test_code_samples.sh | 6 ++ 5 files changed, 135 insertions(+) create mode 100644 docs/code_samples/workflow_execution.txt create mode 100644 src/test/java/com/mindee/workflow/WorkflowTest.java diff --git a/docs/code_samples/workflow_execution.txt b/docs/code_samples/workflow_execution.txt new file mode 100644 index 000000000..b6c70c83e --- /dev/null +++ b/docs/code_samples/workflow_execution.txt @@ -0,0 +1,29 @@ +import com.mindee.MindeeClient; +import com.mindee.input.LocalInputSource; +import com.mindee.parsing.common.WorkflowResponse; +import com.mindee.product.generated.GeneratedV1; +import com.mindee.http.MindeeHttpException; +import java.io.IOException; + +public class SimpleMindeeClient { + + public static void main(String[] args) throws IOException { + String apiKey = "my-api-key"; + String workflowId = "workflow-id"; + String filePath = "/path/to/the/file.ext"; + + // Init a new client + MindeeClient mindeeClient = new MindeeClient(apiKey); + + // Load a file from disk + LocalInputSource inputSource = new LocalInputSource(filePath); + + // Parse the file + WorkflowResponse.Default response = mindeeClient.executeWorkflow( + workflowId, + inputSource + System.out.println(response.toString()); + + } + +} diff --git a/src/main/java/com/mindee/MindeeClient.java b/src/main/java/com/mindee/MindeeClient.java index d982ac26f..0ad32ef0d 100644 --- a/src/main/java/com/mindee/MindeeClient.java +++ b/src/main/java/com/mindee/MindeeClient.java @@ -18,6 +18,7 @@ import com.mindee.pdf.SplitQuery; import com.mindee.product.custom.CustomV1; import com.mindee.product.generated.GeneratedV1; +import com.mindee.parsing.common.WorkflowResponse; import java.io.IOException; import java.net.URL; @@ -323,6 +324,40 @@ private AsyncPredictResponse enqueueAndParse( throw new RuntimeException("Max retries exceeded. Failed to get the document."); } + /** + * Send a local file to a workflow execution. + */ + public WorkflowResponse executeWorkflow( + Class type, + String workflowId, + LocalInputSource localInputSource + + ) throws IOException { + return this.mindeeApi.executeWorkflowPost( + type, + workflowId, + RequestParameters.builder() + .file(localInputSource.getFile()) + .fileName(localInputSource.getFilename()) + .build() + ); + } + + public WorkflowResponse executeWorkflow( + String workflowId, + LocalInputSource localInputSource + + ) throws IOException { + return this.mindeeApi.executeWorkflowPost( + GeneratedV1.class, + workflowId, + RequestParameters.builder() + .file(localInputSource.getFile()) + .fileName(localInputSource.getFilename()) + .build() + ); + } + /** * Send a local file to a Standard prediction API and parse the results. */ diff --git a/src/main/java/com/mindee/parsing/common/WorkflowResponse.java b/src/main/java/com/mindee/parsing/common/WorkflowResponse.java index 5ffe2f5ed..698b9a74e 100644 --- a/src/main/java/com/mindee/parsing/common/WorkflowResponse.java +++ b/src/main/java/com/mindee/parsing/common/WorkflowResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import com.mindee.product.generated.GeneratedV1; import lombok.Data; import lombok.EqualsAndHashCode; @@ -18,4 +19,7 @@ public class WorkflowResponse extends ApiResponse { */ @JsonProperty("execution") Execution execution; + + // Type alias for default type parameter + public static class Default extends WorkflowResponse {} } diff --git a/src/test/java/com/mindee/workflow/WorkflowTest.java b/src/test/java/com/mindee/workflow/WorkflowTest.java new file mode 100644 index 000000000..1f3b26f16 --- /dev/null +++ b/src/test/java/com/mindee/workflow/WorkflowTest.java @@ -0,0 +1,61 @@ +package com.mindee.workflow; + +import com.mindee.MindeeClient; +import com.mindee.http.Endpoint; +import com.mindee.http.MindeeApi; +import com.mindee.input.LocalInputSource; +import com.mindee.parsing.common.Document; +import com.mindee.parsing.common.Execution; +import com.mindee.parsing.common.PredictResponse; +import com.mindee.parsing.common.WorkflowResponse; +import com.mindee.pdf.PdfOperation; +import com.mindee.product.custom.CustomV1; +import com.mindee.product.generated.GeneratedV1; +import java.io.File; +import java.io.IOException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class WorkflowTest { + MindeeClient client; + MindeeApi mindeeApi; + PdfOperation pdfOperation; + + @BeforeEach + public void setUp() { + mindeeApi = Mockito.mock(MindeeApi.class); + pdfOperation = Mockito.mock(PdfOperation.class); + client = new MindeeClient(pdfOperation, mindeeApi); + } + + @Test + void givenAWorkflowMockFileShouldReturnAValidWorkflowObject() + throws IOException { + + File file = new File("src/test/resources/file_types/pdf/blank_1.pdf"); + + WorkflowResponse predictResponse = new WorkflowResponse(); + predictResponse.setExecution(new Execution()); + predictResponse.setApiRequest(null); + Mockito.when( + mindeeApi.executeWorkflowPost( + GeneratedV1.class, + Mockito.any(), + Mockito.any())) + .thenReturn(predictResponse); + + WorkflowResponse workflowResponse = client.executeWorkflow( + "", + new LocalInputSource(file) + ); + + Assertions.assertNotNull(workflowResponse); + Mockito.verify(mindeeApi, Mockito.times(1)) + .predictPost(Mockito.any(), Mockito.any(), Mockito.any()); + } +} diff --git a/tests/test_code_samples.sh b/tests/test_code_samples.sh index c59b48b57..27062b679 100755 --- a/tests/test_code_samples.sh +++ b/tests/test_code_samples.sh @@ -5,6 +5,7 @@ OUTPUT_FILE='SimpleMindeeClient.java' ACCOUNT=$1 ENDPOINT=$2 API_KEY=$3 +WORKFLOW_ID=$4 if [ -z "${ACCOUNT}" ]; then echo "ACCOUNT is required"; exit 1; fi if [ -z "${ENDPOINT}" ]; then echo "ENDPOINT is required"; exit 1; fi @@ -41,6 +42,11 @@ do sed -i "s/my-version/1/" $OUTPUT_FILE fi + if echo "${f}" | grep -q "workflow_execution.txt" + then + sed -i "s/workflow-id/$WORKFLOW_ID/" $OUTPUT_FILE + fi + sed -i "s/my-api-key/$API_KEY/" $OUTPUT_FILE sed -i "s/\/path\/to\/the\/file.ext/src\/test\/resources\/file_types\/pdf\/blank_1.pdf/" $OUTPUT_FILE From e7fcf095e4dfd16ea38abefb397bf2f3977f46d4 Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Wed, 13 Nov 2024 16:54:00 +0100 Subject: [PATCH 05/19] add missing keys to workflow + add test + fix shell script --- src/main/java/com/mindee/MindeeClient.java | 2 +- .../com/mindee/parsing/common/Execution.java | 66 ++++++++++------- .../parsing/common/WorkflowResponse.java | 4 +- .../com/mindee/workflow/WorkflowTest.java | 72 +++++++++++++++---- tests/test_code_samples.sh | 8 +-- 5 files changed, 106 insertions(+), 46 deletions(-) diff --git a/src/main/java/com/mindee/MindeeClient.java b/src/main/java/com/mindee/MindeeClient.java index 0ad32ef0d..95cc7d311 100644 --- a/src/main/java/com/mindee/MindeeClient.java +++ b/src/main/java/com/mindee/MindeeClient.java @@ -13,12 +13,12 @@ import com.mindee.parsing.common.AsyncPredictResponse; import com.mindee.parsing.common.Inference; import com.mindee.parsing.common.PredictResponse; +import com.mindee.parsing.common.WorkflowResponse; import com.mindee.pdf.PdfBoxApi; import com.mindee.pdf.PdfOperation; import com.mindee.pdf.SplitQuery; import com.mindee.product.custom.CustomV1; import com.mindee.product.generated.GeneratedV1; -import com.mindee.parsing.common.WorkflowResponse; import java.io.IOException; import java.net.URL; diff --git a/src/main/java/com/mindee/parsing/common/Execution.java b/src/main/java/com/mindee/parsing/common/Execution.java index ebcbbf359..58802d3a0 100644 --- a/src/main/java/com/mindee/parsing/common/Execution.java +++ b/src/main/java/com/mindee/parsing/common/Execution.java @@ -19,6 +19,25 @@ @AllArgsConstructor @NoArgsConstructor public class Execution implements ApiObject { + /** + * Identifier for the batch to which the execution belongs. + */ + @JsonProperty("batch_name") + private String batchName; + + /** + * The time at which the execution started. + */ + @JsonProperty("created_at") + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime createdAt; + + /** + * File representation within a workflow execution. + */ + @JsonProperty("file") + private ExecutionFile file; + /** * Identifier for the execution. */ @@ -26,31 +45,36 @@ public class Execution implements ApiObject { private String id; /** - * Identifier for the workflow. + * Deserialized inference object. */ - @JsonProperty("workflow_id") - private String workflowId; + @JsonProperty("inference") + private DocT inference; /** - * The time at which the execution started. + * Priority of the execution. */ - @JsonProperty("created_at") + @JsonProperty("priority") + private String priority; + + /** + * The time at which the file was tagged as reviewed. + */ + @JsonProperty("reviewed_at") @JsonDeserialize(using = LocalDateTimeDeserializer.class) - private LocalDateTime createdAt; + private LocalDateTime reviewedAt; /** * The time at which the file was uploaded to a workflow. */ - @JsonProperty("uploaded_at") + @JsonProperty("available_at") @JsonDeserialize(using = LocalDateTimeDeserializer.class) private LocalDateTime availableAt; /** - * The time at which the file was tagged as reviewed. + * Reviewed fields and values. */ - @JsonProperty("reviewed_at") - @JsonDeserialize(using = LocalDateTimeDeserializer.class) - private LocalDateTime reviewedAt; + @JsonProperty("reviewed_prediction") + private GeneratedV1Document reviewedPrediction; /** * Execution Status. @@ -65,21 +89,15 @@ public class Execution implements ApiObject { private String type; /** - * Information about an error that occurred during the job processing. - */ - @JsonProperty("error") - private Error error; - - - /** - * Deserialized inference object. + * The time at which the file was uploaded to a workflow. */ - @JsonProperty("inference") - private DocT inference; + @JsonProperty("uploaded_at") + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime uploadedAt; /** - * Reviewed fields and values. + * Identifier for the workflow. */ - @JsonProperty("reviewed_prediction") - private GeneratedV1Document reviewedPrediction; + @JsonProperty("workflow_id") + private String workflowId; } diff --git a/src/main/java/com/mindee/parsing/common/WorkflowResponse.java b/src/main/java/com/mindee/parsing/common/WorkflowResponse.java index 698b9a74e..4c3d5e2b0 100644 --- a/src/main/java/com/mindee/parsing/common/WorkflowResponse.java +++ b/src/main/java/com/mindee/parsing/common/WorkflowResponse.java @@ -20,6 +20,8 @@ public class WorkflowResponse extends ApiResponse { @JsonProperty("execution") Execution execution; - // Type alias for default type parameter + /** + * Default product is GeneratedV1. + */ public static class Default extends WorkflowResponse {} } diff --git a/src/test/java/com/mindee/workflow/WorkflowTest.java b/src/test/java/com/mindee/workflow/WorkflowTest.java index 1f3b26f16..91103988e 100644 --- a/src/test/java/com/mindee/workflow/WorkflowTest.java +++ b/src/test/java/com/mindee/workflow/WorkflowTest.java @@ -1,15 +1,14 @@ package com.mindee.workflow; +import static org.mockito.Mockito.when; + +import com.fasterxml.jackson.databind.ObjectMapper; import com.mindee.MindeeClient; -import com.mindee.http.Endpoint; import com.mindee.http.MindeeApi; import com.mindee.input.LocalInputSource; -import com.mindee.parsing.common.Document; import com.mindee.parsing.common.Execution; -import com.mindee.parsing.common.PredictResponse; import com.mindee.parsing.common.WorkflowResponse; import com.mindee.pdf.PdfOperation; -import com.mindee.product.custom.CustomV1; import com.mindee.product.generated.GeneratedV1; import java.io.File; import java.io.IOException; @@ -17,20 +16,28 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) public class WorkflowTest { MindeeClient client; + @Mock + MindeeClient mockedClient; MindeeApi mindeeApi; PdfOperation pdfOperation; + private ObjectMapper objectMapper; @BeforeEach public void setUp() { mindeeApi = Mockito.mock(MindeeApi.class); pdfOperation = Mockito.mock(PdfOperation.class); client = new MindeeClient(pdfOperation, mindeeApi); + + MockitoAnnotations.openMocks(this); + objectMapper = new ObjectMapper(); } @Test @@ -39,23 +46,62 @@ void givenAWorkflowMockFileShouldReturnAValidWorkflowObject() File file = new File("src/test/resources/file_types/pdf/blank_1.pdf"); - WorkflowResponse predictResponse = new WorkflowResponse(); - predictResponse.setExecution(new Execution()); - predictResponse.setApiRequest(null); - Mockito.when( + WorkflowResponse workflowResponse = new WorkflowResponse(); + workflowResponse.setExecution(new Execution()); + workflowResponse.setApiRequest(null); + when( mindeeApi.executeWorkflowPost( - GeneratedV1.class, + Mockito.any(), Mockito.any(), Mockito.any())) - .thenReturn(predictResponse); + .thenReturn(workflowResponse); - WorkflowResponse workflowResponse = client.executeWorkflow( + WorkflowResponse execution = client.executeWorkflow( "", new LocalInputSource(file) ); - Assertions.assertNotNull(workflowResponse); + Assertions.assertNotNull(execution); Mockito.verify(mindeeApi, Mockito.times(1)) - .predictPost(Mockito.any(), Mockito.any(), Mockito.any()); + .executeWorkflowPost(Mockito.any(), Mockito.any(), Mockito.any()); + } + + @Test + void sendingADocumentToAnExecutionShouldDeserializeResponseCorrectly() throws IOException { + File jsonFile = new File("src/test/resources/workflows/success.json"); + WorkflowResponse.Default mockResponse = + objectMapper.readValue(jsonFile, WorkflowResponse.Default.class); + + // Mock the executeWorkflow method + when(mockedClient.executeWorkflow(Mockito.anyString(), Mockito.any(LocalInputSource.class))) + .thenReturn(mockResponse); + + // Test execution + String workflowId = "workflow-id"; + String filePath = "src/test/resources/file_types/pdf/blank_1.pdf"; + LocalInputSource inputSource = new LocalInputSource(filePath); + + WorkflowResponse response = mockedClient.executeWorkflow(workflowId, inputSource); + + // Assertions + Assertions.assertNotNull(response); + Assertions.assertNotNull(response.getApiRequest()); + Assertions.assertNull(response.getExecution().getBatchName()); + Assertions.assertNull(response.getExecution().getCreatedAt()); + Assertions.assertNull(response.getExecution().getFile().getAlias()); + Assertions.assertEquals("default_sample.jpg", response.getExecution().getFile().getName()); + Assertions.assertEquals("8c75c035-e083-4e77-ba3b-7c3598bd1d8a", response.getExecution().getId()); + Assertions.assertNull(response.getExecution().getInference()); + Assertions.assertEquals("medium", response.getExecution().getPriority()); + Assertions.assertNull(response.getExecution().getReviewedAt()); + Assertions.assertNull(response.getExecution().getReviewedPrediction()); + Assertions.assertEquals("processing", response.getExecution().getStatus()); + Assertions.assertEquals("manual", response.getExecution().getType()); + Assertions.assertEquals("2024-11-13T13:02:31.699190", response.getExecution().getUploadedAt().toString()); + Assertions.assertEquals("07ebf237-ff27-4eee-b6a2-425df4a5cca6", response.getExecution().getWorkflowId()); + + // Verify that executeWorkflow was called with the correct parameters + Mockito.verify(mockedClient).executeWorkflow(workflowId, inputSource); } + } diff --git a/tests/test_code_samples.sh b/tests/test_code_samples.sh index 27062b679..43e00b2bf 100755 --- a/tests/test_code_samples.sh +++ b/tests/test_code_samples.sh @@ -5,7 +5,6 @@ OUTPUT_FILE='SimpleMindeeClient.java' ACCOUNT=$1 ENDPOINT=$2 API_KEY=$3 -WORKFLOW_ID=$4 if [ -z "${ACCOUNT}" ]; then echo "ACCOUNT is required"; exit 1; fi if [ -z "${ENDPOINT}" ]; then echo "ENDPOINT is required"; exit 1; fi @@ -13,7 +12,7 @@ if [ -z "${ENDPOINT}" ]; then echo "ENDPOINT is required"; exit 1; fi # We need the dependencies otherwise we get class not found exceptions mvn dependency:copy-dependencies -for f in $(find docs/code_samples -maxdepth 1 -name "*.txt" | sort -h) +for f in $(find docs/code_samples -maxdepth 1 -name "*.txt" -not -name "workflow_execution.txt" | sort -h) do echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo "${f}" @@ -42,11 +41,6 @@ do sed -i "s/my-version/1/" $OUTPUT_FILE fi - if echo "${f}" | grep -q "workflow_execution.txt" - then - sed -i "s/workflow-id/$WORKFLOW_ID/" $OUTPUT_FILE - fi - sed -i "s/my-api-key/$API_KEY/" $OUTPUT_FILE sed -i "s/\/path\/to\/the\/file.ext/src\/test\/resources\/file_types\/pdf\/blank_1.pdf/" $OUTPUT_FILE From f5ec75e3fc0162aaa6e1d61ca7d6c4f06beb175e Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Thu, 14 Nov 2024 14:02:05 +0100 Subject: [PATCH 06/19] add priority & alias test --- .../com/mindee/workflow/WorkflowTest.java | 79 ++++++++++++++----- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/src/test/java/com/mindee/workflow/WorkflowTest.java b/src/test/java/com/mindee/workflow/WorkflowTest.java index 91103988e..ca6274b02 100644 --- a/src/test/java/com/mindee/workflow/WorkflowTest.java +++ b/src/test/java/com/mindee/workflow/WorkflowTest.java @@ -30,6 +30,7 @@ public class WorkflowTest { PdfOperation pdfOperation; private ObjectMapper objectMapper; + @BeforeEach public void setUp() { mindeeApi = Mockito.mock(MindeeApi.class); @@ -50,10 +51,11 @@ void givenAWorkflowMockFileShouldReturnAValidWorkflowObject() workflowResponse.setExecution(new Execution()); workflowResponse.setApiRequest(null); when( - mindeeApi.executeWorkflowPost( - Mockito.any(), - Mockito.any(), - Mockito.any())) + mindeeApi.executeWorkflowPost( + Mockito.any(), + Mockito.any(), + Mockito.any() + )) .thenReturn(workflowResponse); WorkflowResponse execution = client.executeWorkflow( @@ -72,35 +74,72 @@ void sendingADocumentToAnExecutionShouldDeserializeResponseCorrectly() throws IO WorkflowResponse.Default mockResponse = objectMapper.readValue(jsonFile, WorkflowResponse.Default.class); - // Mock the executeWorkflow method when(mockedClient.executeWorkflow(Mockito.anyString(), Mockito.any(LocalInputSource.class))) .thenReturn(mockResponse); - // Test execution - String workflowId = "workflow-id"; - String filePath = "src/test/resources/file_types/pdf/blank_1.pdf"; + String workflowId = "07ebf237-ff27-4eee-b6a2-425df4a5cca6"; + String filePath = "src/test/resources/products/financial_document/default_sample.jpg"; LocalInputSource inputSource = new LocalInputSource(filePath); WorkflowResponse response = mockedClient.executeWorkflow(workflowId, inputSource); - // Assertions Assertions.assertNotNull(response); Assertions.assertNotNull(response.getApiRequest()); Assertions.assertNull(response.getExecution().getBatchName()); Assertions.assertNull(response.getExecution().getCreatedAt()); Assertions.assertNull(response.getExecution().getFile().getAlias()); Assertions.assertEquals("default_sample.jpg", response.getExecution().getFile().getName()); - Assertions.assertEquals("8c75c035-e083-4e77-ba3b-7c3598bd1d8a", response.getExecution().getId()); - Assertions.assertNull(response.getExecution().getInference()); - Assertions.assertEquals("medium", response.getExecution().getPriority()); - Assertions.assertNull(response.getExecution().getReviewedAt()); - Assertions.assertNull(response.getExecution().getReviewedPrediction()); - Assertions.assertEquals("processing", response.getExecution().getStatus()); - Assertions.assertEquals("manual", response.getExecution().getType()); - Assertions.assertEquals("2024-11-13T13:02:31.699190", response.getExecution().getUploadedAt().toString()); - Assertions.assertEquals("07ebf237-ff27-4eee-b6a2-425df4a5cca6", response.getExecution().getWorkflowId()); - - // Verify that executeWorkflow was called with the correct parameters + Assertions.assertEquals( + "8c75c035-e083-4e77-ba3b-7c3598bd1d8a", response.getExecution().getId()); + Assertions.assertNull(response.getExecution().getInference()); + Assertions.assertEquals("medium", response.getExecution().getPriority()); + Assertions.assertNull(response.getExecution().getReviewedAt()); + Assertions.assertNull(response.getExecution().getReviewedPrediction()); + Assertions.assertEquals("processing", response.getExecution().getStatus()); + Assertions.assertEquals("manual", response.getExecution().getType()); + Assertions.assertEquals( + "2024-11-13T13:02:31.699190", response.getExecution().getUploadedAt().toString()); + Assertions.assertEquals( + workflowId, response.getExecution().getWorkflowId()); + + Mockito.verify(mockedClient).executeWorkflow(workflowId, inputSource); + } + + + @Test + void sendingADocumentToAnExecutionWithPriorityAndAliasShouldDeserializeResponseCorrectly() throws IOException { + File jsonFile = new File("src/test/resources/workflows/success_low_priority.json"); + WorkflowResponse.Default mockResponse = + objectMapper.readValue(jsonFile, WorkflowResponse.Default.class); + + when(mockedClient.executeWorkflow(Mockito.anyString(), Mockito.any(LocalInputSource.class))) + .thenReturn(mockResponse); + + String workflowId = "07ebf237-ff27-4eee-b6a2-425df4a5cca6"; + String filePath = "src/test/resources/products/financial_document/default_sample.jpg"; + LocalInputSource inputSource = new LocalInputSource(filePath); + + WorkflowResponse response = mockedClient.executeWorkflow(workflowId, inputSource); + + Assertions.assertNotNull(response); + Assertions.assertNotNull(response.getApiRequest()); + Assertions.assertNull(response.getExecution().getBatchName()); + Assertions.assertNull(response.getExecution().getCreatedAt()); + Assertions.assertEquals("low-priority-sample-test", response.getExecution().getFile().getAlias()); + Assertions.assertEquals("default_sample.jpg", response.getExecution().getFile().getName()); + Assertions.assertEquals( + "b743e123-e18c-4b62-8a07-811a4f72afd3", response.getExecution().getId()); + Assertions.assertNull(response.getExecution().getInference()); + Assertions.assertEquals("low", response.getExecution().getPriority()); + Assertions.assertNull(response.getExecution().getReviewedAt()); + Assertions.assertNull(response.getExecution().getReviewedPrediction()); + Assertions.assertEquals("processing", response.getExecution().getStatus()); + Assertions.assertEquals("manual", response.getExecution().getType()); + Assertions.assertEquals( + "2024-11-13T13:17:01.315179", response.getExecution().getUploadedAt().toString()); + Assertions.assertEquals( + workflowId, response.getExecution().getWorkflowId()); + Mockito.verify(mockedClient).executeWorkflow(workflowId, inputSource); } From 76d8d079a1f3e3817b075407c58e2274b01ba999 Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Thu, 14 Nov 2024 14:39:18 +0100 Subject: [PATCH 07/19] remove redundant object + fix typos --- src/main/java/com/mindee/MindeeClient.java | 16 ------- .../com/mindee/parsing/common/ApiObject.java | 46 ------------------- .../com/mindee/parsing/common/Execution.java | 2 +- .../java/com/mindee/parsing/common/Job.java | 2 +- 4 files changed, 2 insertions(+), 64 deletions(-) delete mode 100644 src/main/java/com/mindee/parsing/common/ApiObject.java diff --git a/src/main/java/com/mindee/MindeeClient.java b/src/main/java/com/mindee/MindeeClient.java index 95cc7d311..d897acdfb 100644 --- a/src/main/java/com/mindee/MindeeClient.java +++ b/src/main/java/com/mindee/MindeeClient.java @@ -331,7 +331,6 @@ public WorkflowResponse executeWorkflow( Class type, String workflowId, LocalInputSource localInputSource - ) throws IOException { return this.mindeeApi.executeWorkflowPost( type, @@ -343,21 +342,6 @@ public WorkflowResponse executeWorkflow( ); } - public WorkflowResponse executeWorkflow( - String workflowId, - LocalInputSource localInputSource - - ) throws IOException { - return this.mindeeApi.executeWorkflowPost( - GeneratedV1.class, - workflowId, - RequestParameters.builder() - .file(localInputSource.getFile()) - .fileName(localInputSource.getFilename()) - .build() - ); - } - /** * Send a local file to a Standard prediction API and parse the results. */ diff --git a/src/main/java/com/mindee/parsing/common/ApiObject.java b/src/main/java/com/mindee/parsing/common/ApiObject.java deleted file mode 100644 index 4d682fc17..000000000 --- a/src/main/java/com/mindee/parsing/common/ApiObject.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.mindee.parsing.common; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import java.io.IOException; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.temporal.TemporalAccessor; - -/** - * Interface to help deserialize http datetime objects in a similar fashion. - */ -public interface ApiObject { - /** - * Deserializer for LocalDateTime. - */ - class LocalDateTimeDeserializer extends JsonDeserializer { - - @Override - public LocalDateTime deserialize( - JsonParser jsonParser, - DeserializationContext deserializationContext) throws IOException { - DateTimeFormatter formatter = new DateTimeFormatterBuilder() - .parseCaseInsensitive() - .append(DateTimeFormatter.ISO_LOCAL_DATE) - .appendLiteral('T') - .append(DateTimeFormatter.ISO_LOCAL_TIME) - .optionalStart() - .appendOffsetId() - .toFormatter(); - String dateString = jsonParser.getValueAsString(); - TemporalAccessor temporalAccessor = formatter.parseBest(dateString, ZonedDateTime::from, - LocalDateTime::from); - if (temporalAccessor instanceof ZonedDateTime) { - return ((ZonedDateTime) temporalAccessor).withZoneSameInstant(ZoneOffset.UTC) - .toLocalDateTime(); - } else { - return ((LocalDateTime) temporalAccessor); - } - } - } -} diff --git a/src/main/java/com/mindee/parsing/common/Execution.java b/src/main/java/com/mindee/parsing/common/Execution.java index 58802d3a0..a5bfcab71 100644 --- a/src/main/java/com/mindee/parsing/common/Execution.java +++ b/src/main/java/com/mindee/parsing/common/Execution.java @@ -18,7 +18,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) @AllArgsConstructor @NoArgsConstructor -public class Execution implements ApiObject { +public class Execution { /** * Identifier for the batch to which the execution belongs. */ diff --git a/src/main/java/com/mindee/parsing/common/Job.java b/src/main/java/com/mindee/parsing/common/Job.java index 087899b6c..0bddaad71 100644 --- a/src/main/java/com/mindee/parsing/common/Job.java +++ b/src/main/java/com/mindee/parsing/common/Job.java @@ -17,7 +17,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) @AllArgsConstructor @NoArgsConstructor -public class Job implements ApiObject{ +public class Job{ /** * The time at which the job finished. From 2bdb0f2535d89d4eb7498b9a1b353f790009533b Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Thu, 14 Nov 2024 14:41:48 +0100 Subject: [PATCH 08/19] fix test --- .../com/mindee/workflow/WorkflowTest.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/mindee/workflow/WorkflowTest.java b/src/test/java/com/mindee/workflow/WorkflowTest.java index ca6274b02..1c766085c 100644 --- a/src/test/java/com/mindee/workflow/WorkflowTest.java +++ b/src/test/java/com/mindee/workflow/WorkflowTest.java @@ -59,6 +59,7 @@ void givenAWorkflowMockFileShouldReturnAValidWorkflowObject() .thenReturn(workflowResponse); WorkflowResponse execution = client.executeWorkflow( + GeneratedV1.class, "", new LocalInputSource(file) ); @@ -74,14 +75,17 @@ void sendingADocumentToAnExecutionShouldDeserializeResponseCorrectly() throws IO WorkflowResponse.Default mockResponse = objectMapper.readValue(jsonFile, WorkflowResponse.Default.class); - when(mockedClient.executeWorkflow(Mockito.anyString(), Mockito.any(LocalInputSource.class))) + when(mockedClient.executeWorkflow(GeneratedV1.class, Mockito.anyString(), + Mockito.any(LocalInputSource.class) + )) .thenReturn(mockResponse); String workflowId = "07ebf237-ff27-4eee-b6a2-425df4a5cca6"; String filePath = "src/test/resources/products/financial_document/default_sample.jpg"; LocalInputSource inputSource = new LocalInputSource(filePath); - WorkflowResponse response = mockedClient.executeWorkflow(workflowId, inputSource); + WorkflowResponse response = + mockedClient.executeWorkflow(GeneratedV1.class, workflowId, inputSource); Assertions.assertNotNull(response); Assertions.assertNotNull(response.getApiRequest()); @@ -102,30 +106,35 @@ void sendingADocumentToAnExecutionShouldDeserializeResponseCorrectly() throws IO Assertions.assertEquals( workflowId, response.getExecution().getWorkflowId()); - Mockito.verify(mockedClient).executeWorkflow(workflowId, inputSource); + Mockito.verify(mockedClient).executeWorkflow(GeneratedV1.class, workflowId, inputSource); } @Test - void sendingADocumentToAnExecutionWithPriorityAndAliasShouldDeserializeResponseCorrectly() throws IOException { + void sendingADocumentToAnExecutionWithPriorityAndAliasShouldDeserializeResponseCorrectly() + throws IOException { File jsonFile = new File("src/test/resources/workflows/success_low_priority.json"); WorkflowResponse.Default mockResponse = objectMapper.readValue(jsonFile, WorkflowResponse.Default.class); - when(mockedClient.executeWorkflow(Mockito.anyString(), Mockito.any(LocalInputSource.class))) + when(mockedClient.executeWorkflow(GeneratedV1.class, Mockito.anyString(), + Mockito.any(LocalInputSource.class) + )) .thenReturn(mockResponse); String workflowId = "07ebf237-ff27-4eee-b6a2-425df4a5cca6"; String filePath = "src/test/resources/products/financial_document/default_sample.jpg"; LocalInputSource inputSource = new LocalInputSource(filePath); - WorkflowResponse response = mockedClient.executeWorkflow(workflowId, inputSource); + WorkflowResponse response = + mockedClient.executeWorkflow(GeneratedV1.class, workflowId, inputSource); Assertions.assertNotNull(response); Assertions.assertNotNull(response.getApiRequest()); Assertions.assertNull(response.getExecution().getBatchName()); Assertions.assertNull(response.getExecution().getCreatedAt()); - Assertions.assertEquals("low-priority-sample-test", response.getExecution().getFile().getAlias()); + Assertions.assertEquals( + "low-priority-sample-test", response.getExecution().getFile().getAlias()); Assertions.assertEquals("default_sample.jpg", response.getExecution().getFile().getName()); Assertions.assertEquals( "b743e123-e18c-4b62-8a07-811a4f72afd3", response.getExecution().getId()); @@ -140,7 +149,7 @@ void sendingADocumentToAnExecutionWithPriorityAndAliasShouldDeserializeResponseC Assertions.assertEquals( workflowId, response.getExecution().getWorkflowId()); - Mockito.verify(mockedClient).executeWorkflow(workflowId, inputSource); + Mockito.verify(mockedClient).executeWorkflow(GeneratedV1.class, workflowId, inputSource); } } From d1a4d9083aea20cdf250a1bf7741c50c74dfc610 Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Thu, 14 Nov 2024 14:50:29 +0100 Subject: [PATCH 09/19] fix typo in test --- src/test/java/com/mindee/workflow/WorkflowTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/mindee/workflow/WorkflowTest.java b/src/test/java/com/mindee/workflow/WorkflowTest.java index 1c766085c..e84f68e9c 100644 --- a/src/test/java/com/mindee/workflow/WorkflowTest.java +++ b/src/test/java/com/mindee/workflow/WorkflowTest.java @@ -75,7 +75,7 @@ void sendingADocumentToAnExecutionShouldDeserializeResponseCorrectly() throws IO WorkflowResponse.Default mockResponse = objectMapper.readValue(jsonFile, WorkflowResponse.Default.class); - when(mockedClient.executeWorkflow(GeneratedV1.class, Mockito.anyString(), + when(mockedClient.executeWorkflow(Mockito.eq(GeneratedV1.class), Mockito.anyString(), Mockito.any(LocalInputSource.class) )) .thenReturn(mockResponse); @@ -117,7 +117,7 @@ void sendingADocumentToAnExecutionWithPriorityAndAliasShouldDeserializeResponseC WorkflowResponse.Default mockResponse = objectMapper.readValue(jsonFile, WorkflowResponse.Default.class); - when(mockedClient.executeWorkflow(GeneratedV1.class, Mockito.anyString(), + when(mockedClient.executeWorkflow(Mockito.eq(GeneratedV1.class), Mockito.anyString(), Mockito.any(LocalInputSource.class) )) .thenReturn(mockResponse); From 6ebe9470cbfd0f5e2bb0e7786c7db324bbf56912 Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Thu, 14 Nov 2024 15:53:58 +0100 Subject: [PATCH 10/19] update test sample --- docs/code_samples/workflow_execution.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/code_samples/workflow_execution.txt b/docs/code_samples/workflow_execution.txt index b6c70c83e..e47fd6221 100644 --- a/docs/code_samples/workflow_execution.txt +++ b/docs/code_samples/workflow_execution.txt @@ -18,11 +18,16 @@ public class SimpleMindeeClient { // Load a file from disk LocalInputSource inputSource = new LocalInputSource(filePath); - // Parse the file + // Send the file to a workflow WorkflowResponse.Default response = mindeeClient.executeWorkflow( workflowId, inputSource - System.out.println(response.toString()); + + // Print the workflow ID. + System.out.println(response.getExecution().getId()); + + // Print the inference result. + // System.out.println(response.getExecution().getInference()); } From eb94e7c3785d71bd3acd6dcfea47a14a348093fc Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Fri, 15 Nov 2024 10:33:41 +0100 Subject: [PATCH 11/19] fix typo --- src/main/java/com/mindee/parsing/common/ExecutionFile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/mindee/parsing/common/ExecutionFile.java b/src/main/java/com/mindee/parsing/common/ExecutionFile.java index af51bba90..648640610 100644 --- a/src/main/java/com/mindee/parsing/common/ExecutionFile.java +++ b/src/main/java/com/mindee/parsing/common/ExecutionFile.java @@ -23,7 +23,7 @@ public class ExecutionFile { private String name; /** - * Identifier for the execution. + * Optional alias for the file. */ @JsonProperty("alias") private String alias; From b9376230f31bc408777c675ebe0fcb1a4d23a571 Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Fri, 15 Nov 2024 17:55:19 +0100 Subject: [PATCH 12/19] add alias & priority support + tweak executeworkflow call --- src/main/java/com/mindee/MindeeClient.java | 24 ++++++++++-- src/main/java/com/mindee/WorkflowOptions.java | 38 +++++++++++++++++++ .../java/com/mindee/http/MindeeHttpApi.java | 35 +++++++++++------ .../com/mindee/http/RequestParameters.java | 8 ++++ .../com/mindee/parsing/common/Execution.java | 17 +++++++++ .../mindee/parsing/common/ExecutionFile.java | 6 +++ .../parsing/common/ExecutionPriority.java | 23 +++++++++++ .../com/mindee/workflow/WorkflowTest.java | 13 +++---- 8 files changed, 143 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/mindee/WorkflowOptions.java create mode 100644 src/main/java/com/mindee/parsing/common/ExecutionPriority.java diff --git a/src/main/java/com/mindee/MindeeClient.java b/src/main/java/com/mindee/MindeeClient.java index d897acdfb..227850586 100644 --- a/src/main/java/com/mindee/MindeeClient.java +++ b/src/main/java/com/mindee/MindeeClient.java @@ -327,17 +327,35 @@ private AsyncPredictResponse enqueueAndParse( /** * Send a local file to a workflow execution. */ - public WorkflowResponse executeWorkflow( - Class type, + public WorkflowResponse executeWorkflow( + String workflowId, + LocalInputSource localInputSource, + WorkflowOptions workflowOptions + ) throws IOException { + return this.mindeeApi.executeWorkflowPost( + GeneratedV1.class, + workflowId, + RequestParameters.builder() + .file(localInputSource.getFile()) + .fileName(localInputSource.getFilename()) + .workflowOptions(workflowOptions) + .build() + ); + } + /** + * Send a local file to a workflow execution. + */ + public WorkflowResponse executeWorkflow( String workflowId, LocalInputSource localInputSource ) throws IOException { return this.mindeeApi.executeWorkflowPost( - type, + GeneratedV1.class, workflowId, RequestParameters.builder() .file(localInputSource.getFile()) .fileName(localInputSource.getFilename()) + .workflowOptions(WorkflowOptions.builder().build()) .build() ); } diff --git a/src/main/java/com/mindee/WorkflowOptions.java b/src/main/java/com/mindee/WorkflowOptions.java new file mode 100644 index 000000000..13735835e --- /dev/null +++ b/src/main/java/com/mindee/WorkflowOptions.java @@ -0,0 +1,38 @@ +package com.mindee; + +import com.mindee.parsing.common.ExecutionPriority; +import lombok.Builder; +import lombok.Value; + +/** + * Workflow-specific options. + */ +@Value +public class WorkflowOptions { + /** + * Alias to give to the file. + */ + String alias; + + /** + * Priority to give to the execution. + */ + ExecutionPriority priority; + /** + * Whether to include the full text data for async APIs. + * This performs a full OCR operation on the server and will increase response time and payload + * size. + */ + Boolean fullText; + + @Builder + private WorkflowOptions( + String alias, + ExecutionPriority priority, + Boolean fullText + ) { + this.alias = alias; + this.priority = priority; + this.fullText = fullText == null ? Boolean.FALSE : fullText; + } +} diff --git a/src/main/java/com/mindee/http/MindeeHttpApi.java b/src/main/java/com/mindee/http/MindeeHttpApi.java index b4648aca5..66dcceea9 100644 --- a/src/main/java/com/mindee/http/MindeeHttpApi.java +++ b/src/main/java/com/mindee/http/MindeeHttpApi.java @@ -166,14 +166,14 @@ public AsyncPredictResponse documentQueueGet( mappedResponse.setRawResponse(rawResponse); if ( mappedResponse.getJob() != null - && mappedResponse.getJob().getError() != null - && mappedResponse.getJob().getError().getCode() != null + && mappedResponse.getJob().getError() != null + && mappedResponse.getJob().getError().getCode() != null ) { throw new MindeeHttpException( - 500, - mappedResponse.getJob().getError().getMessage(), - mappedResponse.getJob().getError().getDetails().toString(), - mappedResponse.getJob().getError().getCode() + 500, + mappedResponse.getJob().getError().getMessage(), + mappedResponse.getJob().getError().getDetails().toString(), + mappedResponse.getJob().getError().getCode() ); } return mappedResponse; @@ -301,7 +301,6 @@ public WorkflowResponse executeWorkflowPost( } - private MindeeHttpException getHttpError( JavaType parametricType, CloseableHttpResponse response @@ -325,8 +324,7 @@ private MindeeHttpException getHttpError( ErrorDetails errorDetails = predictResponse.getApiRequest().getError().getDetails(); if (errorDetails != null) { details = errorDetails.toString(); - } - else { + } else { details = ""; } errorCode = predictResponse.getApiRequest().getError().getCode(); @@ -404,12 +402,27 @@ private HttpEntity buildHttpBody( if (Boolean.TRUE.equals(requestParameters.getPredictOptions().getAllWords())) { builder.addTextBody("include_mvision", "true"); } + + if (requestParameters.getWorkflowOptions().getPriority() != null) { + builder.addTextBody( + "priority", + requestParameters.getWorkflowOptions().getPriority().toString() + ); + } + if (requestParameters.getWorkflowOptions().getAlias() != null) { + builder.addTextBody( + "alias", + requestParameters.getWorkflowOptions().getAlias() + ); + } return builder.build(); } else if (requestParameters.getFileUrl() != null) { Map urlMap = new HashMap<>(); urlMap.put("document", requestParameters.getFileUrl()); - return new StringEntity(mapper.writeValueAsString(urlMap), - ContentType.APPLICATION_JSON); + return new StringEntity( + mapper.writeValueAsString(urlMap), + ContentType.APPLICATION_JSON + ); } else { throw new MindeeException("Either document bytes or a document URL are needed"); } diff --git a/src/main/java/com/mindee/http/RequestParameters.java b/src/main/java/com/mindee/http/RequestParameters.java index c4e81f392..50e913227 100644 --- a/src/main/java/com/mindee/http/RequestParameters.java +++ b/src/main/java/com/mindee/http/RequestParameters.java @@ -1,6 +1,7 @@ package com.mindee.http; import com.mindee.PredictOptions; +import com.mindee.WorkflowOptions; import java.net.URL; import lombok.Builder; import lombok.Value; @@ -15,12 +16,14 @@ public class RequestParameters { byte[] file; String fileName; PredictOptions predictOptions; + WorkflowOptions workflowOptions; @Builder private RequestParameters( URL urlInputSource, byte[] file, PredictOptions predictOptions, + WorkflowOptions workflowOptions, String fileName ) { if (file != null && urlInputSource != null) { @@ -31,6 +34,11 @@ private RequestParameters( } else { this.predictOptions = predictOptions; } + if (workflowOptions == null){ + this.workflowOptions = WorkflowOptions.builder().build(); + } else { + this.workflowOptions = workflowOptions; + } this.fileUrl = urlInputSource; this.file = file; this.fileName = fileName; diff --git a/src/main/java/com/mindee/parsing/common/Execution.java b/src/main/java/com/mindee/parsing/common/Execution.java index a5bfcab71..dd75d8f3c 100644 --- a/src/main/java/com/mindee/parsing/common/Execution.java +++ b/src/main/java/com/mindee/parsing/common/Execution.java @@ -100,4 +100,21 @@ public class Execution { */ @JsonProperty("workflow_id") private String workflowId; + + @Override + public String toString() { + return ":batch_name: " + batchName + "\n" + + ":created_at: " + createdAt + "\n" + + ":file: " + file + "\n" + + ":id: " + id + "\n" + + ":inference: " + inference + "\n" + + ":priority: " + priority + "\n" + + ":reviewed_at: " + reviewedAt + "\n" + + ":available_at: " + availableAt + "\n" + + ":reviewed_prediction: " + reviewedPrediction + "\n" + + ":status: " + status + "\n" + + ":type: " + type + "\n" + + ":uploaded_at: " + uploadedAt + "\n" + + ":workflow_id: " + workflowId; + } } diff --git a/src/main/java/com/mindee/parsing/common/ExecutionFile.java b/src/main/java/com/mindee/parsing/common/ExecutionFile.java index 648640610..5795a4050 100644 --- a/src/main/java/com/mindee/parsing/common/ExecutionFile.java +++ b/src/main/java/com/mindee/parsing/common/ExecutionFile.java @@ -27,4 +27,10 @@ public class ExecutionFile { */ @JsonProperty("alias") private String alias; + + + @Override + public String toString() { + return "\n :name: " + name + "\n" + " :alias: " + alias; + } } diff --git a/src/main/java/com/mindee/parsing/common/ExecutionPriority.java b/src/main/java/com/mindee/parsing/common/ExecutionPriority.java new file mode 100644 index 000000000..845300cdf --- /dev/null +++ b/src/main/java/com/mindee/parsing/common/ExecutionPriority.java @@ -0,0 +1,23 @@ +package com.mindee.parsing.common; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Execution priority for a workflow. + */ +public enum ExecutionPriority { + LOW("low"), + MEDIUM("medium"), + HIGH("high"); + + private final String value; + + ExecutionPriority(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} diff --git a/src/test/java/com/mindee/workflow/WorkflowTest.java b/src/test/java/com/mindee/workflow/WorkflowTest.java index e84f68e9c..331fa57e6 100644 --- a/src/test/java/com/mindee/workflow/WorkflowTest.java +++ b/src/test/java/com/mindee/workflow/WorkflowTest.java @@ -59,7 +59,6 @@ void givenAWorkflowMockFileShouldReturnAValidWorkflowObject() .thenReturn(workflowResponse); WorkflowResponse execution = client.executeWorkflow( - GeneratedV1.class, "", new LocalInputSource(file) ); @@ -75,7 +74,7 @@ void sendingADocumentToAnExecutionShouldDeserializeResponseCorrectly() throws IO WorkflowResponse.Default mockResponse = objectMapper.readValue(jsonFile, WorkflowResponse.Default.class); - when(mockedClient.executeWorkflow(Mockito.eq(GeneratedV1.class), Mockito.anyString(), + when(mockedClient.executeWorkflow(Mockito.anyString(), Mockito.any(LocalInputSource.class) )) .thenReturn(mockResponse); @@ -85,7 +84,7 @@ void sendingADocumentToAnExecutionShouldDeserializeResponseCorrectly() throws IO LocalInputSource inputSource = new LocalInputSource(filePath); WorkflowResponse response = - mockedClient.executeWorkflow(GeneratedV1.class, workflowId, inputSource); + mockedClient.executeWorkflow(workflowId, inputSource); Assertions.assertNotNull(response); Assertions.assertNotNull(response.getApiRequest()); @@ -106,7 +105,7 @@ void sendingADocumentToAnExecutionShouldDeserializeResponseCorrectly() throws IO Assertions.assertEquals( workflowId, response.getExecution().getWorkflowId()); - Mockito.verify(mockedClient).executeWorkflow(GeneratedV1.class, workflowId, inputSource); + Mockito.verify(mockedClient).executeWorkflow(workflowId, inputSource); } @@ -117,7 +116,7 @@ void sendingADocumentToAnExecutionWithPriorityAndAliasShouldDeserializeResponseC WorkflowResponse.Default mockResponse = objectMapper.readValue(jsonFile, WorkflowResponse.Default.class); - when(mockedClient.executeWorkflow(Mockito.eq(GeneratedV1.class), Mockito.anyString(), + when(mockedClient.executeWorkflow(Mockito.anyString(), Mockito.any(LocalInputSource.class) )) .thenReturn(mockResponse); @@ -127,7 +126,7 @@ void sendingADocumentToAnExecutionWithPriorityAndAliasShouldDeserializeResponseC LocalInputSource inputSource = new LocalInputSource(filePath); WorkflowResponse response = - mockedClient.executeWorkflow(GeneratedV1.class, workflowId, inputSource); + mockedClient.executeWorkflow(workflowId, inputSource); Assertions.assertNotNull(response); Assertions.assertNotNull(response.getApiRequest()); @@ -149,7 +148,7 @@ void sendingADocumentToAnExecutionWithPriorityAndAliasShouldDeserializeResponseC Assertions.assertEquals( workflowId, response.getExecution().getWorkflowId()); - Mockito.verify(mockedClient).executeWorkflow(GeneratedV1.class, workflowId, inputSource); + Mockito.verify(mockedClient).executeWorkflow(workflowId, inputSource); } } From 882f6f3b4a1e509ac078000e76fe2b0430723dda Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Mon, 18 Nov 2024 11:59:41 +0100 Subject: [PATCH 13/19] fix example script --- docs/code_samples/workflow_execution.txt | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/code_samples/workflow_execution.txt b/docs/code_samples/workflow_execution.txt index e47fd6221..316ce7488 100644 --- a/docs/code_samples/workflow_execution.txt +++ b/docs/code_samples/workflow_execution.txt @@ -19,16 +19,23 @@ public class SimpleMindeeClient { LocalInputSource inputSource = new LocalInputSource(filePath); // Send the file to a workflow - WorkflowResponse.Default response = mindeeClient.executeWorkflow( - workflowId, - inputSource + WorkflowResponse response = mindeeClient.executeWorkflow( + workflowId, + inputSource + ); + + + // Alternatively: give an alias to the document + // WorkflowResponse response = mindeeClient.executeWorkflow( + // workflowId, + // inputSource, + // WorkflowOptions.builder().alias("my-alias").build() + // ); // Print the workflow ID. System.out.println(response.getExecution().getId()); // Print the inference result. // System.out.println(response.getExecution().getInference()); - } - } From 92f276be118a22ad8ee7577198fefc14ffae839c Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Wed, 20 Nov 2024 14:40:26 +0100 Subject: [PATCH 14/19] :arrow_up: bump wiremock dependency --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index cafd7a6e8..3ef78e5df 100644 --- a/pom.xml +++ b/pom.xml @@ -363,7 +363,7 @@ ${org.mockito.inline.version} - com.github.tomakehurst + org.wiremock wiremock ${wiremock.version} test @@ -419,7 +419,7 @@ 1.18.32 1.6.12 UTF-8 - 2.27.2 + 3.9.2 From 462ce5ab0254574c836807587f17264bab3d1c60 Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Wed, 20 Nov 2024 14:55:16 +0100 Subject: [PATCH 15/19] downgrade wiremock version bc of course they would drop java 8 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3ef78e5df..43d423e5a 100644 --- a/pom.xml +++ b/pom.xml @@ -382,7 +382,7 @@ scm:git:git://github.com/mindee/mindee-api-java.git scm:git:ssh://github.com:mindee/mindee-api-java.git - http://github.com/mindee/mindee-api-java/tree/main + https://github.com/mindee/mindee-api-java/tree/main @@ -419,7 +419,7 @@ 1.18.32 1.6.12 UTF-8 - 3.9.2 + 2.35.1 From 58f87ab03b48ac50e1b27f9d539c80e3f2290c3f Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Wed, 20 Nov 2024 14:57:43 +0100 Subject: [PATCH 16/19] properly fix wiremock version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 43d423e5a..d66a2f64f 100644 --- a/pom.xml +++ b/pom.xml @@ -363,7 +363,7 @@ ${org.mockito.inline.version} - org.wiremock + com.github.tomakehurst wiremock ${wiremock.version} test From 71e844565fc83c03db495e5fc1ca4f506ac0b456 Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Wed, 20 Nov 2024 16:14:27 +0100 Subject: [PATCH 17/19] restore pom.xml, add integration test --- .github/workflows/integration-tests.yml | 1 + pom.xml | 2 +- .../java/com/mindee/http/MindeeHttpApi.java | 4 +- .../parsing/common/ExecutionPriority.java | 1 + .../java/com/mindee/workflow/WorkflowIT.java | 53 +++++++++++++++++++ 5 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/mindee/workflow/WorkflowIT.java diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 40f9a9837..5eb3fd97b 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -33,5 +33,6 @@ jobs: - name: Verify with Maven env: MINDEE_API_KEY: ${{ secrets.MINDEE_API_KEY_SE_TESTS }} + WORKFLOW_ID: ${{ secrets.WORKFLOW_ID_SE_TESTS }} run: | mvn clean test-compile failsafe:integration-test failsafe:verify diff --git a/pom.xml b/pom.xml index d66a2f64f..9e8c25138 100644 --- a/pom.xml +++ b/pom.xml @@ -419,7 +419,7 @@ 1.18.32 1.6.12 UTF-8 - 2.35.1 + 2.27.2 diff --git a/src/main/java/com/mindee/http/MindeeHttpApi.java b/src/main/java/com/mindee/http/MindeeHttpApi.java index 66dcceea9..7356b1cb7 100644 --- a/src/main/java/com/mindee/http/MindeeHttpApi.java +++ b/src/main/java/com/mindee/http/MindeeHttpApi.java @@ -406,13 +406,13 @@ private HttpEntity buildHttpBody( if (requestParameters.getWorkflowOptions().getPriority() != null) { builder.addTextBody( "priority", - requestParameters.getWorkflowOptions().getPriority().toString() + requestParameters.getWorkflowOptions().getPriority().getValue() ); } if (requestParameters.getWorkflowOptions().getAlias() != null) { builder.addTextBody( "alias", - requestParameters.getWorkflowOptions().getAlias() + requestParameters.getWorkflowOptions().getAlias().toLowerCase() ); } return builder.build(); diff --git a/src/main/java/com/mindee/parsing/common/ExecutionPriority.java b/src/main/java/com/mindee/parsing/common/ExecutionPriority.java index 845300cdf..0cde417cc 100644 --- a/src/main/java/com/mindee/parsing/common/ExecutionPriority.java +++ b/src/main/java/com/mindee/parsing/common/ExecutionPriority.java @@ -1,5 +1,6 @@ package com.mindee.parsing.common; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; /** diff --git a/src/test/java/com/mindee/workflow/WorkflowIT.java b/src/test/java/com/mindee/workflow/WorkflowIT.java new file mode 100644 index 000000000..ea8d4ce2f --- /dev/null +++ b/src/test/java/com/mindee/workflow/WorkflowIT.java @@ -0,0 +1,53 @@ +package com.mindee.workflow; + +import com.mindee.MindeeClient; +import com.mindee.MindeeException; +import com.mindee.WorkflowOptions; +import com.mindee.input.LocalInputSource; +import com.mindee.parsing.common.Execution; +import com.mindee.parsing.common.ExecutionPriority; +import com.mindee.parsing.common.WorkflowResponse; +import com.mindee.product.generated.GeneratedV1; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class WorkflowIT { + private static MindeeClient client; + private static LocalInputSource financialDocumentInputSource; + private static String currentDateTime; + + @BeforeAll + static void clientSetUp() throws IOException { + LocalDateTime now = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH:mm:ss"); + currentDateTime = now.format(formatter); + client = new MindeeClient(); + financialDocumentInputSource = new LocalInputSource( + "src/test/resources/products/financial_document/default_sample.jpg" + ); + } + + protected Execution getFinancialDocumentWorkflow(String workflowId) throws + IOException, MindeeException { + + WorkflowOptions options = WorkflowOptions.builder().alias("java-" + currentDateTime).priority( + ExecutionPriority.LOW).build(); + WorkflowResponse response = + client.executeWorkflow(workflowId, financialDocumentInputSource, options); + return response.getExecution(); + } + + + @Test + public void givenAPDF_shouldExtractInvoicesStrict() throws IOException { + Execution execution = getFinancialDocumentWorkflow(System.getenv("WORKFLOW_ID")); + + Assertions.assertEquals("low", execution.getPriority()); + Assertions.assertEquals("java-" + currentDateTime, execution.getFile().getAlias()); + + } +} From 400ae351c23c0600f3fdbd00f7ca7cc26ba147e6 Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Wed, 20 Nov 2024 16:22:34 +0100 Subject: [PATCH 18/19] fix test name --- src/test/java/com/mindee/workflow/WorkflowIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/mindee/workflow/WorkflowIT.java b/src/test/java/com/mindee/workflow/WorkflowIT.java index ea8d4ce2f..06c265820 100644 --- a/src/test/java/com/mindee/workflow/WorkflowIT.java +++ b/src/test/java/com/mindee/workflow/WorkflowIT.java @@ -43,7 +43,7 @@ protected Execution getFinancialDocumentWorkflow(String workflowId) @Test - public void givenAPDF_shouldExtractInvoicesStrict() throws IOException { + public void givenAWorkflowIDShouldReturnACorrectWorkflowObject() throws IOException { Execution execution = getFinancialDocumentWorkflow(System.getenv("WORKFLOW_ID")); Assertions.assertEquals("low", execution.getPriority()); From bbb1bc32ec30ed8d76c0bb637de82be2f47e27ef Mon Sep 17 00:00:00 2001 From: sebastianMindee Date: Tue, 26 Nov 2024 11:04:11 +0100 Subject: [PATCH 19/19] add public url --- src/main/java/com/mindee/WorkflowOptions.java | 11 ++++++++++- src/main/java/com/mindee/http/MindeeHttpApi.java | 6 ++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/mindee/WorkflowOptions.java b/src/main/java/com/mindee/WorkflowOptions.java index 13735835e..2ad7bbab9 100644 --- a/src/main/java/com/mindee/WorkflowOptions.java +++ b/src/main/java/com/mindee/WorkflowOptions.java @@ -18,6 +18,7 @@ public class WorkflowOptions { * Priority to give to the execution. */ ExecutionPriority priority; + /** * Whether to include the full text data for async APIs. * This performs a full OCR operation on the server and will increase response time and payload @@ -25,14 +26,22 @@ public class WorkflowOptions { */ Boolean fullText; + /** + * A unique, encrypted URL for accessing the document validation interface without requiring + * authentication. + */ + String publicUrl; + @Builder private WorkflowOptions( String alias, ExecutionPriority priority, - Boolean fullText + Boolean fullText, + String publicUrl ) { this.alias = alias; this.priority = priority; this.fullText = fullText == null ? Boolean.FALSE : fullText; + this.publicUrl = publicUrl; } } diff --git a/src/main/java/com/mindee/http/MindeeHttpApi.java b/src/main/java/com/mindee/http/MindeeHttpApi.java index 7356b1cb7..5e7515283 100644 --- a/src/main/java/com/mindee/http/MindeeHttpApi.java +++ b/src/main/java/com/mindee/http/MindeeHttpApi.java @@ -415,6 +415,12 @@ private HttpEntity buildHttpBody( requestParameters.getWorkflowOptions().getAlias().toLowerCase() ); } + if (requestParameters.getWorkflowOptions().getPublicUrl() != null) { + builder.addTextBody( + "public_url", + requestParameters.getWorkflowOptions().getPublicUrl() + ); + } return builder.build(); } else if (requestParameters.getFileUrl() != null) { Map urlMap = new HashMap<>();