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/docs/code_samples/workflow_execution.txt b/docs/code_samples/workflow_execution.txt
new file mode 100644
index 000000000..316ce7488
--- /dev/null
+++ b/docs/code_samples/workflow_execution.txt
@@ -0,0 +1,41 @@
+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);
+
+ // Send the file to a workflow
+ 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());
+ }
+}
diff --git a/pom.xml b/pom.xml
index cafd7a6e8..9e8c25138 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
diff --git a/src/main/java/com/mindee/MindeeClient.java b/src/main/java/com/mindee/MindeeClient.java
index d982ac26f..227850586 100644
--- a/src/main/java/com/mindee/MindeeClient.java
+++ b/src/main/java/com/mindee/MindeeClient.java
@@ -13,6 +13,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 com.mindee.pdf.PdfBoxApi;
import com.mindee.pdf.PdfOperation;
import com.mindee.pdf.SplitQuery;
@@ -323,6 +324,42 @@ 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(
+ 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(
+ GeneratedV1.class,
+ workflowId,
+ RequestParameters.builder()
+ .file(localInputSource.getFile())
+ .fileName(localInputSource.getFilename())
+ .workflowOptions(WorkflowOptions.builder().build())
+ .build()
+ );
+ }
+
/**
* Send a local file to a Standard prediction API and parse the results.
*/
diff --git a/src/main/java/com/mindee/WorkflowOptions.java b/src/main/java/com/mindee/WorkflowOptions.java
new file mode 100644
index 000000000..2ad7bbab9
--- /dev/null
+++ b/src/main/java/com/mindee/WorkflowOptions.java
@@ -0,0 +1,47 @@
+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;
+
+ /**
+ * A unique, encrypted URL for accessing the document validation interface without requiring
+ * authentication.
+ */
+ String publicUrl;
+
+ @Builder
+ private WorkflowOptions(
+ String alias,
+ ExecutionPriority priority,
+ 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/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..5e7515283 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,12 @@ private MindeeHttpApi(
this.documentUrlFromEndpoint = this.buildBaseUrl.andThen(
(url) -> url.concat("/documents/queue/"));
}
+
+ if (workflowUrlFromEndpoint != null) {
+ this.workflowUrlFromId = workflowUrlFromEndpoint;
+ } else {
+ this.workflowUrlFromId = this.buildWorkflowBaseUrl;
+ }
}
/**
@@ -149,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;
@@ -243,6 +260,47 @@ 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
@@ -266,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();
@@ -289,6 +346,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
@@ -341,12 +402,33 @@ 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().getValue()
+ );
+ }
+ if (requestParameters.getWorkflowOptions().getAlias() != null) {
+ builder.addTextBody(
+ "alias",
+ 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<>();
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
new file mode 100644
index 000000000..dd75d8f3c
--- /dev/null
+++ b/src/main/java/com/mindee/parsing/common/Execution.java
@@ -0,0 +1,120 @@
+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 {
+ /**
+ * 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.
+ */
+ @JsonProperty("id")
+ private String id;
+
+ /**
+ * Deserialized inference object.
+ */
+ @JsonProperty("inference")
+ private DocT inference;
+
+ /**
+ * Priority of the execution.
+ */
+ @JsonProperty("priority")
+ private String priority;
+
+ /**
+ * The time at which the file was tagged as reviewed.
+ */
+ @JsonProperty("reviewed_at")
+ @JsonDeserialize(using = LocalDateTimeDeserializer.class)
+ private LocalDateTime reviewedAt;
+
+ /**
+ * The time at which the file was uploaded to a workflow.
+ */
+ @JsonProperty("available_at")
+ @JsonDeserialize(using = LocalDateTimeDeserializer.class)
+ private LocalDateTime availableAt;
+
+ /**
+ * Reviewed fields and values.
+ */
+ @JsonProperty("reviewed_prediction")
+ private GeneratedV1Document reviewedPrediction;
+
+ /**
+ * Execution Status.
+ */
+ @JsonProperty("status")
+ private String status;
+
+ /**
+ * Execution type.
+ */
+ @JsonProperty("type")
+ private String type;
+
+ /**
+ * The time at which the file was uploaded to a workflow.
+ */
+ @JsonProperty("uploaded_at")
+ @JsonDeserialize(using = LocalDateTimeDeserializer.class)
+ private LocalDateTime uploadedAt;
+
+ /**
+ * Identifier for the workflow.
+ */
+ @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
new file mode 100644
index 000000000..5795a4050
--- /dev/null
+++ b/src/main/java/com/mindee/parsing/common/ExecutionFile.java
@@ -0,0 +1,36 @@
+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;
+
+ /**
+ * Optional alias for the file.
+ */
+ @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..0cde417cc
--- /dev/null
+++ b/src/main/java/com/mindee/parsing/common/ExecutionPriority.java
@@ -0,0 +1,24 @@
+package com.mindee.parsing.common;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+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/main/java/com/mindee/parsing/common/Job.java b/src/main/java/com/mindee/parsing/common/Job.java
index 6e6a1213c..0bddaad71 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{
/**
- * 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..4c3d5e2b0
--- /dev/null
+++ b/src/main/java/com/mindee/parsing/common/WorkflowResponse.java
@@ -0,0 +1,27 @@
+package com.mindee.parsing.common;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.mindee.product.generated.GeneratedV1;
+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;
+
+ /**
+ * Default product is GeneratedV1.
+ */
+ public static class Default extends WorkflowResponse {}
+}
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);
+ }
+}
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..06c265820
--- /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 givenAWorkflowIDShouldReturnACorrectWorkflowObject() throws IOException {
+ Execution execution = getFinancialDocumentWorkflow(System.getenv("WORKFLOW_ID"));
+
+ Assertions.assertEquals("low", execution.getPriority());
+ Assertions.assertEquals("java-" + currentDateTime, execution.getFile().getAlias());
+
+ }
+}
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..331fa57e6
--- /dev/null
+++ b/src/test/java/com/mindee/workflow/WorkflowTest.java
@@ -0,0 +1,154 @@
+package com.mindee.workflow;
+
+import static org.mockito.Mockito.when;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.mindee.MindeeClient;
+import com.mindee.http.MindeeApi;
+import com.mindee.input.LocalInputSource;
+import com.mindee.parsing.common.Execution;
+import com.mindee.parsing.common.WorkflowResponse;
+import com.mindee.pdf.PdfOperation;
+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.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
+ void givenAWorkflowMockFileShouldReturnAValidWorkflowObject()
+ throws IOException {
+
+ File file = new File("src/test/resources/file_types/pdf/blank_1.pdf");
+
+ WorkflowResponse workflowResponse = new WorkflowResponse();
+ workflowResponse.setExecution(new Execution());
+ workflowResponse.setApiRequest(null);
+ when(
+ mindeeApi.executeWorkflowPost(
+ Mockito.any(),
+ Mockito.any(),
+ Mockito.any()
+ ))
+ .thenReturn(workflowResponse);
+
+ WorkflowResponse execution = client.executeWorkflow(
+ "",
+ new LocalInputSource(file)
+ );
+
+ Assertions.assertNotNull(execution);
+ Mockito.verify(mindeeApi, Mockito.times(1))
+ .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);
+
+ 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.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(
+ 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);
+ }
+
+}
diff --git a/tests/test_code_samples.sh b/tests/test_code_samples.sh
index c59b48b57..43e00b2bf 100755
--- a/tests/test_code_samples.sh
+++ b/tests/test_code_samples.sh
@@ -12,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}"